<?php

/**
 * 跑步相关数据 Model
 */
class runModel
{

    /**
     * 基类
     * @var object
     */
    private $base;

    /**
     * Mysql 连接
     * @var resources
     */
    private $db;

    /**
     * Redis 连接
     * @var resources
     */
    private $redis;

    public function __construct(& $base)
    {
        $this->base = $base;
        $this->db = & $this->base->db;
        $this->redis = & $this->base->redis;
    }

     /**
     * 上传用户单次跑步数据
     * @param array  $runData
     * @return boolean
     */
    public function uploadUserRunData($runData)
    {
        $did = 0;
        if(!isset($runData['mileage']) || !isset($runData['elapsedtime']) || !isset($runData['calorie']) || !isset($runData['order_id']) || !isset($runData['updatetime']))
        {
            return $did;
        }
  
        $runData['elapsedtime'] < 1 && $runData['elapsedtime'] = 1;
        $runData['mileage'] = $runData['mileage'] < 0.01 ? 0.01 :round($runData['mileage'], 2);

        $runData['calorie'] = $runData['calorie'] < 1 ? 0 : intval($runData['calorie']);

        $runData['addtime'] = $this->base->time;
        $runData['cid'] = $this->base->cid;
        $runData['version'] = $this->base->vn;
        $uid = $this->base->uid;
        
        if(!isset($runData['overSpeed']))
        {
            $runData['overSpeed'] = 0;
        }

        if(!empty($uid))
        {
            $runData['uid'] = $uid;
            // 异常数据类型
            // $runData['overSpeed'] = $this->checkCheatRun($uid, $runData['mileage'], $runData['elapsedtime'], $runData['updatetime'], $runData['detail_speed']);
            if($runData['overSpeed'] == 0)
            {
                $runData['medal'] = isset($runData['medal']) ? $this->base->load('medal')->verifyRunMedal($uid, $runData['medal'], $runData['updatetime']) : '[]';
            }
        }
        else
        {
            $vid = $this->base->vid;
            $runData['vid'] = $vid;
            unset($runData['record_img'],$runData['recordImgCount'],$runData['medal'],$runData['five_time'],$runData['ten_time'],$runData['half_mtime'],$runData['mara_time']);
        }
        
        $runData['tipsString'] && $runData['tipsString'] = common::mysql_real_escape_string($runData['tipsString']);
        $runData['gearId'] && $runData['gearId'] = common::mysql_real_escape_string($runData['gearId']);
        
        // 跑步坐标写入方式
        $coordinate = $runData['coordinate'];
        $detail_speed_curve = $runData['detail_speed_curve'];
        $detail_elevation = $runData['detail_elevation'];
        $detail_elevation_curve = $runData['detail_elevation_curve'];
        $detail_elevation_fold = $runData['detail_elevation_fold'];
        $detail_footsteps = $runData['detail_footsteps'];
        $detail_footsteps_curve = $runData['detail_footsteps_curve'];
        $detail_footsteps_fold = $runData['detail_footsteps_fold'];
        $detail_stride = $runData['detail_stride'];
        is_array($coordinate) && $coordinate = json_encode($coordinate);
        $coordinate = common::mysql_real_escape_string($coordinate);

        $detail_speed_curve && $detail_speed_curve = common::mysql_real_escape_string($detail_speed_curve);
        $detail_elevation && $detail_elevation = common::mysql_real_escape_string($detail_elevation);
        $detail_elevation_curve && $detail_elevation_curve = common::mysql_real_escape_string($detail_elevation_curve);
        $detail_elevation_fold && $detail_elevation_fold = common::mysql_real_escape_string($detail_elevation_fold);
        $detail_footsteps && $detail_footsteps = common::mysql_real_escape_string($detail_footsteps);
        $detail_footsteps_curve && $detail_footsteps_curve = common::mysql_real_escape_string($detail_footsteps_curve);
        $detail_footsteps_fold && $detail_footsteps_fold = common::mysql_real_escape_string($detail_footsteps_fold);
        $detail_stride && $detail_stride = common::mysql_real_escape_string($detail_stride);

        $runExtData = compact('coordinate', 'detail_speed_curve', 'detail_elevation', 'detail_elevation_curve', 'detail_elevation_fold', 'detail_footsteps', 'detail_footsteps_curve', 'detail_footsteps_fold', 'detail_stride');
        unset($runData['coordinate'], $runData['detail_speed_curve'], $runData['detail_elevation'], $runData['detail_elevation_curve'], $runData['detail_footsteps'], $runData['detail_footsteps_curve'], $runData['detail_stride'], $runData['detail_elevation_fold'], $runData['detail_footsteps_fold']);

        $runData['speed'] = isset($runData['speed']) ? $runData['speed'] : $runData['mileage']/($runData['elapsedtime']/3600);
        $runData['speed'] = number_format($runData['speed'],3);
        
        //暂时不存储跑步天数
        $tmp_run_days = isset($runData['tmp_run_days']) ? $runData['tmp_run_days'] : 0;
        unset($runData['tmp_run_days']);
        
        $insertStr = common::arrayToString($runData);

        if(!empty($uid))
        {
            $isOrderId = $this->redis->hget(REDIS_PREFIX . 'runDataOrder_' . $uid, $runData['order_id']);

            if(!$isOrderId)
            {
                $userInfo = $this->base->load('client')->getUserInfo($uid);
                $did = $this->base->db->insert("insert HIGH_PRIORITY into r_data set {$insertStr} on duplicate key update {$insertStr}");
            }

            if($did)
            {
                // 记录OrderId
                $this->redis->hset(REDIS_PREFIX . 'runDataOrder_' . $uid, $runData['order_id'], 1);

                // 上传附加数据
                $runExtData['did'] = $did;
                $this->base->db->insertRow('r_data_ext', $runExtData, 2);

                // 记录变更数据                    
                 $modify = array(
                    'uid' => $uid,
                    'modify_type' => 0,
                    'add_time' => $this->base->time,
                    'modify_time' => $this->base->time
                );   
                    
                $this->runDataModify($did, $modify);

                // 如果用户数据异常，不作以下操作
                if($runData['overSpeed'] > 0)
                {
                    return $did;
                }
                
                // 更新用户累计数据
                $runData['tmp_run_days'] = $tmp_run_days;
                $this->updateUserRecord($runData, $did);

                //发正能量
                if($this->base->vn >=1400 || ($this->base->vn >= 1200 && $this->base->projectId == 2))
                {
                    if(isset($runData['target_rate']) && $runData['target_rate'] >= 1)
                    {
                        $this->base->load('client')->userEnergyChange($uid, 'target', $runData['mileage']);
                    }
                    elseif($runData['mileage'] >= 1)
                    {
                        $this->base->load('client')->userEnergyChange($uid, 'run', $runData['mileage']);
                    }
                }
                // 更新用户好友排行榜
                if($this->base->vn >= 1500)
                {
                    //$this->updateUserFStandings($uid, $runData['mileage']);
                }
                // 更新用户最近跑步记录
                $runRecord = array('mileage'        => $runData['mileage'],
                                   'elapsedtime'    => $runData['elapsedtime'],
                                   'city'           => $runData['city'],
                                   'calorie'        => $runData['calorie'],
                                   'updatetime'     => $runData['updatetime']
                                   );

                //$this->base->load('client')->getLatestRunRecord($uid, $runRecord);

                // 更新用户跑步等级信息
                //$this->base->load('client')->getUserLevelInfo($uid, TRUE);
                // 更新用户里程排名
                $this->setClientMileageStandingsRank($uid, round($userInfo['total_mileage'] + $runData['mileage'], 3));
                // 更新用户日跑步数据
                //unset($runRecord['city']);
                $this->base->load('paome/cup')->addUserRunData($did);

            }
        }
        else
        {
            $insertStr .= ' ,coordinate = "'.$coordinate.'"';
            $did = $this->base->db->insert("insert HIGH_PRIORITY into r_visitor_data set {$insertStr} on duplicate key update {$insertStr}");
            if($did)
            {
                $this->redis->hset(REDIS_PREFIX . 'runDataVOrder_' . $vid, $runData['order_id'], 1);
                // 更新游客累计数据
                $visitorInfo = $this->base->load('client')->getVisitorInfo($vid);
                $upData = array(
                    'total_mileage' => round($visitorInfo['total_mileage'] + $runData['mileage'], 2),
                    'total_elapsedtime' => $visitorInfo['total_elapsedtime'] + $runData['elapsedtime'],
                    'total_calorie' => round($visitorInfo['total_calorie'] + $runData['calorie'], 1),
                    'total_rate' => $visitorInfo['total_rate'] + 1
                );

                // $speed > $visitorInfo['max_speed'] && $upData['max_speed'] = $speed;
                $runData['mileage'] > $visitorInfo['max_mileage'] && $upData['max_mileage'] = $runData['mileage'];
                $runData['elapsedtime'] > $visitorInfo['max_elapsedtime'] && $upData['max_elapsedtime'] = $runData['elapsedtime'];
                $this->base->load('client')->saveVisitorInfo($vid, $upData);
            }
        }
        return $did;
    }

    /**
     * 删除用户单次跑步数据
     * @param int $order_id
     * @return array() $result
     */
    public function deleteUserRunData($order_id)
    {
        $uid = $this->base->uid;
        $vid = $this->base->vid;
        $did = 0;
        $is_success = 0;
        $mileage = 0;
        $updatetime = 0;
        $result = array('uid' => $uid,
                        'is_success' => & $is_success,
                        'did' => & $did,
                        'mileage' => & $mileage,
                        'updatetime' => & $updatetime
                    );
  
        $upRunData = array('is_delete' => 1);
        if(!empty($uid))
        {

            // $runData = $this->db->getRowTable('r_data', array(), "uid = '{$uid}' and order_id = '{$order_id}' and is_delete = 0");
            $runData = $this->db->getRow("select * from r_data where uid='{$uid}' and order_id = '{$order_id}' and is_delete = 0");

         //   common::pr($runData);exit;
            if(empty($runData))
            {
                return $result;
            }
            $did = $runData['did'];
            $upRunData['did'] = $did;
            $is_success = $this->db->updateRowTable('r_data', $upRunData) ? 1 : 0;
            if($is_success == 1)
            {
                $modify = array(
                                'uid' => $uid,
                                'modify_type' => 1,
                                'modify_time' => $this->base->time
                    );
                $this->runDataModify($did, $modify);
            }
            if($is_success == 1 && $runData['overSpeed'] == 0)
            {
                $mileage = $runData['mileage'];
                $updatetime = $runData['updatetime'];
                //更新用户信息和用户排行
                $userInfo = $this->base->load('client')->getUserInfo($uid);
                $upData = array();
                $maxData = $this->db->getRow("select max(speed) as max_speed, max(mileage) as max_mileage, max(elapsedtime) as max_elapsedtime from r_data where uid = '{$uid}' and is_delete = 0 and overSpeed = 0 limit 1");

                $upData['total_mileage'] = $userInfo['total_mileage'] - $runData['mileage'];
                $upData['total_elapsedtime'] = $userInfo['total_elapsedtime'] - $runData['elapsedtime'];
                $upData['total_calorie'] = $userInfo['total_calorie'] - $runData['calorie'];
                $upData['level'] = common::getLevel($upData['total_mileage']);
                $upData['total_rate'] = $userInfo['total_rate'] - 1;
                $upData['total_mileage'] < 0 && $upData['total_mileage'] = 0;
                $upData['total_elapsedtime'] < 0 && $upData['total_elapsedtime'] = 0;
                $upData['total_calorie'] < 0 && $upData['total_calorie'] = 0;
                $upData['total_rate'] < 0 && $upData['total_rate'] = 0;
                if($userInfo['level'] > $upData['level'])
                {
                    $this->runLevelUpRecord($uid, 0-$upData['level'], $upData['total_mileage']);
                }
                // 更新用户好友排行榜
                if($this->base->vn >=1500)
                {
                    $this->updateUserFStandings($uid, 0-$runData['mileage'], $runData['addtime']);
                }
                $upData['max_speed'] = $maxData['max_speed'];
                $upData['max_mileage'] = $maxData['max_mileage'];
                $upData['max_elapsedtime'] = $maxData['max_elapsedtime'];
                
                //更新最佳成绩对应的did   v_2.8.9
                if(!empty($userInfo['best_record'])){
                    $upData['best_record'] = json_decode($userInfo['best_record'], true);
                    foreach ($upData['best_record'] as $k => $v) {
                        if($v == $did){
                            //根据最佳成绩查询对应的did
                            if($k == 'max_mileage'){
                                $dataInfo = $this->db->getRow("select did from r_data where uid = {$uid} and mileage = '{$maxData['max_mileage']}' and is_delete = 0 and overSpeed = 0 limit 1");
                                $upData['best_record'][$k] = $dataInfo['did'];
                            }
                            if($k == 'max_speed'){
                                $dataInfo = $this->db->getRow("select did from r_data where uid = {$uid} and speed = '{$maxData['max_speed']}' and is_delete = 0 and overSpeed = 0 limit 1");
                                $upData['best_record'][$k] = $dataInfo['did'];
                            }
                            if($k == 'max_elapsedtime'){
                                $dataInfo = $this->db->getRow("select did from r_data where uid = {$uid} and elapsedtime = '{$maxData['max_elapsedtime']}' and is_delete = 0 and overSpeed = 0 limit 1");
                                $upData['best_record'][$k] = $dataInfo['did'];
                            }
                        }
                    }
                    $upData['best_record'] = json_encode($upData['best_record']);
                }

                $this->base->load('client')->setUserInfo($uid, $upData);
                // 更新用户最近跑步记录
                $this->base->load('client')->getLatestRunRecord($uid, array(), true);
                // 更新用户跑步等级信息
                $this->base->load('client')->getUserLevelInfo($uid, TRUE);
                // 更新用户里程排名
                $this->setClientMileageStandingsRank($uid, $this->base->userInfo['total_mileage']);
                $this->addDayRunData($uid, array('mileage'=>-$runData['mileage'],'elapsedtime'=>-$runData['elapsedtime'],'calorie'=>-$runData['calorie'],'updatetime'=>$runData['updatetime'], 'delete' => true));
            }
        }
        else
        {
            $run_data = $this->db->getRow("select * from r_visitor_data where vid = '{$vid}' and order_id = '{$order_id}' limit 1");
            $did = $run_data['did'];
            if(empty($did))
            {
                return 1;
            }
            $is_success = $this->db->delDataTable('r_visitor_data', " is_delete =1 and did = {$did}") ? 1 : 0;
            $old_uid = $this->base->db->getone("select old_uid from r_visitor where vid = '{$vid}'");
            if($is_success == 1 && $old_uid > 1)
            {
                //更新用户信息和用户排行
                $visitorInfo = $this->base->load('client')->getVisitorInfo($vid);
                $upData = array();
                $maxData = $this->db->getRow("select max(speed) as max_speed, max(mileage) as max_mileage, max(elapsedtime) as max_elapsedtime from r_visitor_data where vid = '{$vid}'");

                $upData['total_mileage'] = $visitorInfo['total_mileage'] - $run_data['mileage'];
                $upData['total_elapsedtime'] = $visitorInfo['total_elapsedtime'] - $run_data['elapsedtime'];
                $upData['total_calorie'] = $visitorInfo['total_calorie'] - $run_data['calorie'];

                $upData['max_speed'] = $maxData['max_speed'];
                $upData['max_mileage'] = $maxData['max_mileage'];
                $upData['max_elapsedtime'] = $maxData['max_elapsedtime'];

                $this->base->load('client')->saveVisitorInfo($vid, $upData);

                // 更新用户里程排名
                $this->setClientMileageStandingsRank($old_uid, $upData['total_mileage']);
            }
        }
        return $result;
    }
    /**
     * 删除用户单次跑步数据
     * @param int $did
     * @return boolean
     */
    public function deleteUserRunDataBYDid($did, $type=0, $id = 0)
    {
        $uid = $type == 1 ? $id : 0;
        $vid = $type == 2 ? $id : 0;

        $did = intval($did);
        $is_success = 0;
        $mileage = 0;
        $updatetime = 0;
        $result = array('uid' => $uid,
                        'is_success' => & $is_success,
                        'did' => & $did,
                        'mileage' => & $mileage,
                        'updatetime' => & $updatetime
                    );
        $upRunData = array('is_delete' => 1);

        if(!empty($uid))
        {
            $runData = $this->db->getRowTable('r_data', array(), "uid = '{$uid}' and did = '{$did}' and is_delete = 0");
            $did = $runData['did'];
            if(empty($did))
            {
                return $result;
            }
            $upRunData['did'] = $did;

            $is_success = $this->db->updateRowTable('r_data', $upRunData) ? 1 : 0;

            if($is_success == 1)
            {
                $modify = array(
                                'uid' => $uid,
                                'modify_type' => 1,
                                'modify_time' => $this->base->time
                    );
                $this->runDataModify($did, $modify);
            }

            if($is_success == 1 && $runData['overSpeed'] == 0)
            {
                $mileage = $runData['mileage'];
                $updatetime = $runData['updatetime'];

                //更新用户信息和用户排行
                $userInfo = $this->base->load('client')->getUserInfo($uid);
                $upData = array();
                $maxData = $this->db->getRow("select max(speed) as max_speed, max(mileage) as max_mileage, max(elapsedtime) as max_elapsedtime from r_data where uid = '{$uid}' limit 1");

                $upData['total_mileage'] = $userInfo['total_mileage'] - $runData['mileage'];
                $upData['total_elapsedtime'] = $userInfo['total_elapsedtime'] - $runData['elapsedtime'];
                $upData['total_calorie'] = $userInfo['total_calorie'] - $runData['calorie'];

                $upData['max_speed'] = $maxData['max_speed'];
                $upData['max_mileage'] = $maxData['max_mileage'];
                $upData['max_elapsedtime'] = $maxData['max_elapsedtime'];
                $upData['total_rate'] = $userInfo['total_rate'] - 1;

                $upData['total_mileage'] < 0 && $upData['total_mileage'] = 0;
                $upData['total_elapsedtime'] < 0 && $upData['total_elapsedtime'] = 0;
                $upData['total_calorie'] < 0 && $upData['total_calorie'] = 0;
                $upData['total_rate'] < 0 && $upData['total_rate'] = 0;

                //更新最佳成绩对应的did   v_2.8.9
                if(!empty($userInfo['best_record'])){
                    $upData['best_record'] = json_decode($userInfo['best_record'], true);
                    foreach ($upData['best_record'] as $k => $v) {
                        if($v == $did){
                            //根据最佳成绩查询对应的did
                            if($k == 'max_mileage'){
                                $dataInfo = $this->db->getRow("select did from r_data where uid = {$uid} and mileage = {$maxData['max_mileage']} and is_delete = 0 and overSpeed = 0 limit 1");
                                $upData['best_record'][$k] = $dataInfo['did'];
                            }
                            if($k == 'max_speed'){
                                $dataInfo = $this->db->getRow("select did from r_data where uid = {$uid} and speed = {$maxData['max_speed']} and is_delete = 0 and overSpeed = 0 limit 1");
                                $upData['best_record'][$k] = $dataInfo['did'];
                            }
                            if($k == 'max_elapsedtime'){
                                $dataInfo = $this->db->getRow("select did from r_data where uid = {$uid} and elapsedtime = {$maxData['max_elapsedtime']} and is_delete = 0 and overSpeed = 0 limit 1");
                                $upData['best_record'][$k] = $dataInfo['did'];
                            }
                        }
                    }
                    $upData['best_record'] = json_encode($upData['best_record']);
                }

                $this->base->load('client')->setUserInfo($uid, $upData);

                $upData['level'] = common::getLevel($upData['total_mileage']);
                if($userInfo['level'] > $upData['level'])
                {
                    $this->runLevelUpRecord($uid, 0-$upData['level'], $upData['total_mileage']);
                }
                // 更新用户好友排行榜
                if($this->base->vn >=1500)
                {
                    $this->updateUserFStandings($uid, 0-$runData['mileage'], $runData['addtime']);
                }
                // 更新用户最近跑步记录
                $this->base->load('client')->getLatestRunRecord($uid, array(), true);
                // 更新用户跑步等级信息
                $this->base->load('client')->getUserLevelInfo($uid, TRUE);
                // 更新用户里程排名
                $this->setClientMileageStandingsRank($uid, $upData['total_mileage']);
                // $this->addDayRunData($uid, array('mileage'=>-$runData['mileage'],'elapsedtime'=>-$runData['elapsedtime'],'calorie'=>-$runData['calorie'],'updatetime'=>$runData['updatetime'],'delete' => true));
            }
        }
        else
        {
            $run_data = $this->db->getRow("select * from r_visitor_data where vid = '{$vid}' and did = '{$did}' and is_delete = 0 limit 1");
            $did = $run_data['did'];
            if(empty($did))
            {
                return 0;
            }

            $upRunData['did'] = $did;
            $is_success = $this->db->updateRowTable('r_visitor_data', $upRunData) ? 1 : 0;
            $old_uid = $this->db->getone("select old_uid from r_visitor where vid = '{$vid}'");
            if($is_success == 1 && $old_uid > 1)
            {
                //更新用户信息和用户排行
                $visitorInfo = $this->base->load('client')->getVisitorInfo($vid);
                $upData = array();
                $maxData = $this->db->getRow("select max(speed) as max_speed, max(mileage) as max_mileage, max(elapsedtime) as max_elapsedtime from r_visitor_data where vid = '{$vid}'");

                $upData['total_mileage'] = $visitorInfo['total_mileage'] - $run_data['mileage'];
                $upData['total_elapsedtime'] = $visitorInfo['total_elapsedtime'] - $run_data['elapsedtime'];
                $upData['total_calorie'] = $visitorInfo['total_calorie'] - $run_data['calorie'];

                $upData['max_speed'] = $maxData['max_speed'];
                $upData['max_mileage'] = $maxData['max_mileage'];
                $upData['max_elapsedtime'] = $maxData['max_elapsedtime'];

                $this->base->load('client')->saveVisitorInfo($vid, $upData);

                // 更新用户最近跑步记录
                $this->base->load('client')->getLatestRunRecord($user['uid'], array(), true);
                // 更新用户里程排名
                $this->setClientMileageStandingsRank($old_uid, $upData['total_mileage']);
            }
        }
        return $result;
    }
    /**
     * 修改用户单次跑步数据
     * @param int $did
     * @return boolean
     */
    public function modifyRunData($uid, $did, $record_img,$recordImgCount=0, $run_mood, $expression_id)
    {
        if(empty($uid))
        {
          $_ENV['error']->getErrors(201);
          exit;
        }
        if(empty($did))
        {
          $_ENV['error']->getErrors(101);
          exit;
        }
        if($this->db->getOne("select did from r_data where did= '{$did}' and uid = '{$uid}'"))
        {
            $upRunData = compact('did','record_img','recordImgCount','run_mood','expression_id');
            return $this->db->updateRowTable('r_data', $upRunData) !== false ? 1 : 0;
        }
        return 0;
    }
    /**
     * 恢复已删除的用户单次跑步数据
     * @param int $did
     * @return boolean
     */
    public function recoverRunDataRunDataBYDid($did, $type=0, $id = 0)
    {
        $uid = $type == 1 ? $id : 0;
        $vid = $type == 2 ? $id : 0;

        $upRunData = array('is_delete' => 0);

        if(!empty($uid))
        {
            $runData = $this->db->getRowTable('r_data', array(), "uid = '{$uid}' and did = '{$did}' and is_delete = 1");
            $did = $runData['did'];
            if(empty($did))
            {
                return 0;
            }
            $upRunData['did'] = $did;
            $is_success = $this->db->updateRowTable('r_data', $upRunData) ? 1 : 0;

            if($is_success == 1)
            {
                // 记录变更数据
                $modify = array(
                                'uid' => $uid,
                                'modify_type' => 0,
                                'add_time' => $this->base->time,
                                'modify_time' => $this->base->time
                    );
                $this->runDataModify($did, $modify);
                //更新用户信息和用户排行
                $userInfo = $this->base->load('client')->getUserInfo($uid);
                $upData = array();
                $maxData = $this->db->getRow("select max(speed) as max_speed, max(mileage) as max_mileage, max(elapsedtime) as max_elapsedtime from r_data where uid = '{$uid}' and is_delete = 0 and overSpeed = 0 limit 1");

                $upData['total_mileage'] = $userInfo['total_mileage'] + $runData['mileage'];
                $upData['total_elapsedtime'] = $userInfo['total_elapsedtime'] + $runData['elapsedtime'];
                $upData['total_calorie'] = $userInfo['total_calorie'] + $runData['calorie'];

                $upData['max_speed'] = $maxData['max_speed'];
                $upData['max_mileage'] = $maxData['max_mileage'];
                $upData['max_elapsedtime'] = $maxData['max_elapsedtime'];
                $upData['total_rate'] = $userInfo['total_rate'] + 1;
				$upData['level'] = common::getLevel($upData['total_mileage']);

                //更新最佳成绩对应的did   v_2.8.9
                if(!empty($userInfo['best_record'])){
                    $upData['best_record'] = json_decode($userInfo['best_record'], true);
                    foreach ($upData['best_record'] as $k => $v) {
                        if($v == $did){
                            //根据最佳成绩查询对应的did
                            if($k == 'max_mileage'){
                                $dataInfo = $this->db->getRow("select did from r_data where uid = {$uid} and mileage = {$maxData['max_mileage']} and is_delete = 0 and overSpeed = 0 limit 1");
                                $upData['best_record'][$k] = $dataInfo['did'];
                            }
                            if($k == 'max_speed'){
                                $dataInfo = $this->db->getRow("select did from r_data where uid = {$uid} and speed = {$maxData['max_speed']} and is_delete = 0 and overSpeed = 0 limit 1");
                                $upData['best_record'][$k] = $dataInfo['did'];
                            }
                            if($k == 'max_elapsedtime'){
                                $dataInfo = $this->db->getRow("select did from r_data where uid = {$uid} and elapsedtime = {$maxData['max_elapsedtime']} and is_delete = 0 and overSpeed = 0 limit 1");
                                $upData['best_record'][$k] = $dataInfo['did'];
                            }
                        }
                    }
                    $upData['best_record'] = json_encode($upData['best_record']);
                }

                $this->base->load('client')->setUserInfo($uid, $upData);
                if($userInfo['level'] < $upData['level'])
                {
                    $this->runLevelUpRecord($uid, $upData['level'], $upData['total_mileage']);
                }
                // 更新用户好友排行榜
                $this->updateUserFStandings($uid, $runData['mileage'], $runData['addtime']);
                // 更新用户最近跑步记录
                $this->base->load('client')->getLatestRunRecord($uid, array(), true);
                // 更新用户跑步等级信息
                $this->base->load('client')->getUserLevelInfo($uid, TRUE);
                // 更新用户里程排名
                $this->setClientMileageStandingsRank($uid, $upData['total_mileage']);
                $this->addDayRunData($uid, array('mileage'=>$runData['mileage'],'elapsedtime'=>$runData['elapsedtime'],'calorie'=>$runData['calorie'],'updatetime'=>$runData['updatetime']));
            }
        }
        else
        {
            $run_data = $this->db->getRow("select * from r_visitor_data where vid = '{$vid}' and did = '{$did}' and is_delete=1 limit 1");
            $did = $run_data['did'];
            if(empty($did))
            {
                return 0;
            }

            $upRunData['did'] = $did;
            $is_success = $this->db->updateRowTable('r_visitor_data', $upRunData) ? 1 : 0;
            $old_uid = $this->db->getone("select old_uid from r_visitor where vid = '{$vid}'");
            if($is_success == 1 && $old_uid > 1)
            {
                //更新用户信息和用户排行
                $visitorInfo = $this->base->load('client')->getVisitorInfo($vid);
                $upData = array();
                $maxData = $this->db->getRow("select max(speed) as max_speed, max(mileage) as max_mileage, max(elapsedtime) as max_elapsedtime from r_visitor_data where vid = '{$vid}'");

                $upData['total_mileage'] = $visitorInfo['total_mileage'] + $run_data['mileage'];
                $upData['total_elapsedtime'] = $visitorInfo['total_elapsedtime'] + $run_data['elapsedtime'];
                $upData['total_calorie'] = $visitorInfo['total_calorie'] + $run_data['calorie'];

                $upData['max_speed'] = $maxData['max_speed'];
                $upData['max_mileage'] = $maxData['max_mileage'];
                $upData['max_elapsedtime'] = $maxData['max_elapsedtime'];

                $this->base->load('client')->saveVisitorInfo($vid, $upData);

                // 更新用户最近跑步记录
                $this->base->load('client')->getLatestRunRecord($user['uid'], array(), true);
                // 更新用户里程排名
                $this->setClientMileageStandingsRank($old_uid, $upData['total_mileage']);
            }
        }
        return $is_success;
    }
    /**
     * 根据用户跑步did获取跑步数据
     *  @param int $did
     *  @return array $run_data
    */
    public function getRunDataByDid($did)
    {
        if(empty($did) || intval($did) <= 0)
        {
            $_ENV['error']->getErrors(101);
            exit;
        }
        $uid = $this->base->uid;
        $data = array();
        if($uid)
        {
            $data = $this->db->getRow("select d.*,de.coordinate,de.detail_speed_curve,de.detail_elevation,de.detail_elevation_curve,de.detail_footsteps,de.detail_footsteps_curve,de.detail_stride,de.detail_elevation_fold,de.detail_footsteps_fold from r_data d left join r_data_ext de on d.did=de.did where uid = '{$uid}' and d.did = '{$did}' and is_delete = 0");
            if(!empty($data))
            {
                unset($data['uid']);
            }
        }
        else
        {
            $vid = $this->base->vid;
            $data = $this->base->db->getRowTable('r_visitor_data', array(), "vid = '{$vid}' and did = '{$did}' and is_delete = 0");
            if(!empty($data))
            {
                unset($data['vid']);
            }
        }
        if(!empty($data))
        {
            unset($data['addtime'],$data['recordImgCount'],$data['is_delete']);

            $data['record_img'] = json_decode($data['record_img'], true);
            $medal = !empty($data['medal']) ? json_decode($data['medal'], TRUE) : array();
            if(!empty($medal) && (($this->base->vn > 1850 && $this->base->projectId == 1) || $this->base->projectId == 2 || $this->base->projectId == 3))
            {
                $temMedal = array();
                foreach ($medal as $medal_id) {
                    $medalInfo = $this->base->load('medal')->getMedalInfo($medal_id);
                    if($medalInfo)
                    {
                        $temMedal[] = array('medal_id' => $medal_id,
                                             'medal_name'   => $medalInfo['medal_name'],
                                             'word'   => $medalInfo['word'],
                                             'isCustom'   => $medalInfo['isCustom']
                                            );
                    }
                }
                $data['medal'] = $temMedal;
            }
            unset($data['is_delete'], $data['version'], $data['cid']);
            $m = round($data['mileage'], 2);
            $t = common::sec2time($data['elapsedtime']);

            /*
            $uncompress = @gzuncompress($data['coordinate']);
            $uncompress = $uncompress !== false ? stripslashes($uncompress) : $data['coordinate'];
            $data['coordinate'] = !empty($data['coordinate']) ? $uncompress : array();
            $data['coordinate'] = !empty($data['coordinate']) ? json_decode($data['coordinate'], TRUE) : array();
            $data['point_coordinate'] = !empty($data['point_coordinate']) ? json_decode($data['point_coordinate'], TRUE) : array();
            $data['detail_speed'] = !empty($data['detail_speed']) ? json_decode($data['detail_speed'], TRUE) : array();
            $data['southWestPoint'] = !empty($data['southWestPoint']) ? json_decode($data['southWestPoint'], TRUE) : array();
            $data['northEastPoint'] = !empty($data['northEastPoint']) ? json_decode($data['northEastPoint'], TRUE) : array();
            */
            
            $coordinate = @base64_decode($data['coordinate']);
            $uncompress = $coordinate ? @gzuncompress($$coordinate) : FALSE;
            !$uncompress && $uncompress = @gzuncompress($data['coordinate']);
            $data['coordinate'] = !$uncompress ? $data['coordinate'] : stripslashes($uncompress);
            $data['coordinate'] = trim($data['coordinate'], '"');
            $data['coordinate'] = $data['coordinate'] ? json_decode($data['coordinate'], true) : array();

            $data['point_coordinate'] = stripslashes($data['point_coordinate']);
            $data['point_coordinate'] = trim($data['point_coordinate'], '"');
            $data['point_coordinate'] = $data['point_coordinate'] ? json_decode($data['point_coordinate'], true) : array();
            $data['detail_speed'] = stripslashes($data['detail_speed']);
            $data['detail_speed'] = trim($data['detail_speed'], '"');
            $data['detail_speed'] = $data['detail_speed'] ? json_decode($data['detail_speed'], true) : array();
            $data['southWestPoint'] = stripslashes($data['southWestPoint']);
            $data['southWestPoint'] = trim($data['southWestPoint'], '"');
            $data['southWestPoint'] = $data['southWestPoint'] ? json_decode($data['southWestPoint'], true) : array();
            $data['northEastPoint'] = stripslashes($data['northEastPoint']);
            $data['northEastPoint'] = trim($data['northEastPoint'], '"');
            $data['northEastPoint'] = $data['northEastPoint'] ? json_decode($data['northEastPoint'], true) : array();

            $data['detail_speed_curve'] = !empty($data['detail_speed_curve']) ? json_decode($data['detail_speed_curve'], TRUE) : [];
            $data['detail_elevation_curve'] = !empty($data['detail_elevation_curve']) ? json_decode($data['detail_elevation_curve'], TRUE) : [];
            $data['detail_elevation_fold'] = !empty($data['detail_elevation_fold']) ? json_decode($data['detail_elevation_fold'], TRUE) : [];
            $data['detail_footsteps_curve'] = !empty($data['detail_footsteps_curve']) ? json_decode($data['detail_footsteps_curve'], TRUE) : [];
            $data['detail_footsteps_fold'] = !empty($data['detail_footsteps_fold']) ? json_decode($data['detail_footsteps_fold'], TRUE) : [];
            
            $data['desc'] = '你跑了' . $m . '公里用时' . $t;
        }
        return $data;
    }




    /**
     * 根据did批量获取跑步数据
     *  @param string $dids
     *  @return array $data
    */
    public function getBatchRunDataByDid($uid, $dids)
    {
        $data = array();
        $dids = json_decode($dids, true);
        if(empty($uid) || !is_array($dids) || empty($dids))
        {
            return $data;
        }
        $data = $this->db->getAll("select d.*,de.coordinate,de.detail_speed_curve,de.detail_elevation,de.detail_elevation_curve,de.detail_footsteps,de.detail_footsteps_curve,de.detail_stride,de.detail_elevation_fold,de.detail_footsteps_fold from r_data d left join r_data_ext de on d.did=de.did where uid = '{$uid}' and is_delete = 0 and d.did ".$this->base->load('push')->db_create_in($dids).' order by d.did DESC');
        if($data)
        {
            foreach ($data as & $value) {
                unset($value['addtime'],$value['is_delete']);
                $value['record_img'] = json_decode($value['record_img'], true);
                $medal = !empty($value['medal']) ? json_decode($value['medal'], TRUE) : array();
                if(!empty($medal) && (($this->base->vn > 1850 && $this->base->projectId == 1) || $this->base->projectId == 2 || $this->base->projectId == 3))
                {
                    $temMedal = array();
                    foreach ($medal as $medal_id) {
                        $medalInfo = $this->base->load('medal')->getMedalInfo($medal_id);
                        if($medalInfo)
                        {
                            $temMedal[] = array('medal_id' => $medal_id,
                                                 'medal_name'   => $medalInfo['medal_name'],
                                                 'word'   => $medalInfo['word'],
                                                 'isCustom'   => $medalInfo['isCustom']
                                );
                        }
                    }
                    $value['medal'] = $temMedal;
                }
                unset($data['is_delete'], $data['version'], $data['cid'], $data['overSpeed']);
                $m = round($value['mileage'], 2);
                $t = common::sec2time($value['elapsedtime']);

                $coordinate = @base64_decode($value['coordinate']);
                $uncompress = $coordinate ? @gzuncompress($coordinate) : FALSE;
                !$uncompress && $uncompress = @gzuncompress($value['coordinate']);
                $uncompress = $uncompress ? stripslashes($uncompress) : $value['coordinate'];
                $value['coordinate'] = !empty($value['coordinate']) ? $uncompress : '';
                $value['coordinate'] = !empty($value['coordinate']) ? json_decode($value['coordinate'], TRUE) : '';
                $value['coordinate'] = $this->reCoordinate($value['coordinate']);
                $value['point_coordinate'] = !empty($value['point_coordinate']) ? json_decode($value['point_coordinate'], TRUE) : '';
                $value['detail_speed'] = !empty($value['detail_speed']) ? json_decode($value['detail_speed'], TRUE) : '';
                $value['southWestPoint'] = !empty($value['southWestPoint']) ? json_decode($value['southWestPoint'], TRUE) : '';
                $value['northEastPoint'] = !empty($value['northEastPoint']) ? json_decode($value['northEastPoint'], TRUE) : '';

                $value['detail_speed_curve'] = $value['detail_speed_curve'] ? json_decode($value['detail_speed_curve'], TRUE) : [];
                $value['detail_elevation_curve'] = $value['detail_elevation_curve'] ? json_decode($value['detail_elevation_curve'], TRUE) : [];
                $value['detail_elevation_fold'] = $value['detail_elevation_fold'] ? json_decode($value['detail_elevation_fold'], TRUE) : [];
                $value['detail_footsteps_curve'] = $value['detail_footsteps_curve'] ? json_decode($value['detail_footsteps_curve'], TRUE) : [];
                $value['detail_footsteps_fold'] = $value['detail_footsteps_fold'] ? json_decode($value['detail_footsteps_fold'], TRUE) : [];

                $value['desc'] = '你跑了' . $m . '公里用时' . $t;
                $value['month'] = date("Ym");
            }
        }

        return $data;
    }
    /**
     * 获取did范围内跑步记录did（不包括边界值）
     *  @param int $did
     *  @return array $history_data
    */
    public function getRangeRunDids($start, $end)
    {
        $result = array();
        $uid = $this->base->uid;
        if(!$uid)
        {
            return $result;
        }
        $result = $this->db->getCol("select did from r_data where uid = '{$uid}' and did > '{$start}' and did < '{$end}' order by did ASC");

        return $result;
    }
    /**
     * 保存分享图片到数据库
     * @param type $did
     * @param type $share_img
     */
    public function saveShareImg($did, $share_img)
    {
        $result = FALSE;
        $data = array(
            'did' => $did,
            'share_img' => $share_img
        );
        $result = $this->db->updateRowTable('r_data', $data);
        return $result;
    }

    /**
     * 获取指定用户单月的跑步统计数据
     * @param int $uid
     * @param int $month
     * @return array
     */
    public function getClientRunDataStats($uid, $month = 0)
    {
        $result = array(
            'tabs' => array(),
            'total' => array(
                'elapsedtime' => 0,
                'mileage' => 0,
                'speed' => 0,
                'min_time' => 0,
            ),
            'data' => array(),
        );

        $clientMonth = $this->db->getCol("select month from r_data_month where uid='{$uid}' order by dmid desc");

        if ($clientMonth && (!$month || in_array($month, $clientMonth)))
        {
            $count = count($clientMonth);

            if (!$month)
            {
                if ($count > 1)
                {
                    $result['tabs']['prev'] = array(
                        'val' => date('Y-m', $clientMonth[1]),
                        'title' => date('Y年m月', $clientMonth[1])
                    );
                }

                $month = $clientMonth[0];
            } else
            {
                $pos = array_search($month, $clientMonth);

                if ($pos < $count - 1)
                {
                    $result['tabs']['prev'] = array(
                        'val' => date('Y-m', $clientMonth[$pos + 1]),
                        'title' => date('Y年m月', $clientMonth[$pos + 1])
                    );
                }

                if ($pos && $pos <= $count - 1)
                {
                    $result['tabs']['next'] = array(
                        'val' => date('Y-m', $clientMonth[$pos - 1]),
                        'title' => date('Y年m月', $clientMonth[$pos - 1])
                    );
                }
            }

            $result['tabs']['current'] = array(
                'val' => date('Y-m', $month),
                'title' => date('Y年m月', $month)
            );

            $maxMonth = strtotime('+1 month', $month);
            $runData = $this->db->getAll("select elapsedtime,mileage,speed,legspeed,calorie,addtime from r_data where uid='{$uid}' and addtime>={$month} and addtime<{$maxMonth} order by addtime asc");

            if ($runData)
            {//$result['data']
                foreach ($runData as $k => $v)
                {
                    $result['total']['elapsedtime'] += $v['elapsedtime'];
                    $result['total']['mileage'] += $v['mileage'];
                    $result['total']['speed'] = ($v['speed'] > $result['total']['speed']) ? $v['speed'] : $result['total']['speed'];
                    $result['total']['min_time'] = ($v['legspeed'] > $result['total']['min_time']) ? $v['legspeed'] : $result['total']['min_time'];

                    $day = date('d', $v['addtime']);

                    if (!isset($result['data'][$day]))
                    {
                        $first = TRUE;
                        $result['data'][$day] = array('elapsedtime' => 0, 'mileage' => 0, 'speed' => 0, 'calorie' => 0, 'day' => intval($day));
                    } else
                    {
                        $first = FALSE;
                    }

                    $result['data'][$day]['elapsedtime'] += $v['elapsedtime'];
                    $result['data'][$day]['mileage'] += $v['mileage'];
                    $result['data'][$day]['speed'] += $v['speed'];
                    !$first && $result['data'][$day]['speed'] = round($result['data'][$day]['speed'] / 2, 1);
                    $result['data'][$day]['calorie'] += $v['calorie'];
                }

                $result['data'] = array_values($result['data']);
            }
        }

        return $result;
    }

    /**
     * 获取跑步里程排行榜数据
     * @param int $topNum
     * @return array
     */
    public function getMileageStandings($type = "all", $topNum = 100)
    {
        $result = array(
            'my_rank' => array(),
            'data' => array(),
        );

        if($this->base->uid)
        {
            // 我的排名
            $userInfo = $this->base->load('client')->getUserInfo($this->base->uid);
            $result['my_rank'] = array(
                'rank' => $this->getClientMileageStandingsRank($this->base->uid),
                'level' => $userInfo['level'],
                'nickname' => $userInfo['nickname'],
                'header' => $userInfo['header'],
                'gender' => $userInfo['gender'],
                'total_mileage' => sprintf("%.2f", $userInfo['total_mileage'])
            );
             $result['my_rank']['further'] = $this->getClientMileageGap($result['my_rank']['rank']);
        }
        else
        {
            $vid = $this->base->vid;
            $old_uid = $this->base->db->getone("select old_uid from r_visitor where vid = '{$vid}'");
            if($this->base->vn < '1100')
            {
                $visitorInfo = $this->base->load('client')->getVisitorInfo($vid);
                $result['my_rank'] = array(
                    'rank' => 0,
                    // 'level' => common::getLevel($visitorInfo['total_elapsedtime']),
                    'nickname' => $visitorInfo['nickname'],
                    'header' => $visitorInfo['header'],
                    'total_mileage' => sprintf("%.2f", $visitorInfo['total_mileage']),
                    'further' => 0
                );
            }
            else
            {
                $result['my_rank'] = array(
                    'rank' => 0,
                    'level' => 0,
                    'nickname' => 'Runner',
                    'header' => '',
                    'total_mileage' => 0,
                    'further' => '您未绑定账户，无法显示排名',
                );
            }
            $result['data'] = array();
        }

        $result['data'] = $this->getMileageStandingTopInfo($topNum);
        return $result;
    }

    /**
     * 获取指定用户的历史跑步数据
     * @param int $uid
     * @return array
     */
    public function getClientRunHistoryData($uid, $page = 1, $did=0, $direc='next', $offset=20, $beginTime = NULL, $endTime = NULL)
    {
        $result = $this->getClientRunData($uid, $page, $did, $direc, $offset, $beginTime, $endTime);
        if ($result)
        {
            foreach ($result as $k => & $v)
            {
                // 处理跑步记录图片
                $v['record_img'] = json_decode($v['record_img'], true);
                if($this->base->vn < '1100')
                {
                    $v['record_img'] = common::realUrl($v['record_img']);
                    $v['record_img'] = '';
                    $v['record_img_thumb'] = str_replace('/record/', '/record/thumb/', $v['record_img']);
                    $v['record_img_thumb'] = '';
                }
                $detailSpeedArray = @json_decode($v['detail_speed']);
                // if(is_array($detailSpeedArray))
                // {
                //     if($this->base->projectId == 1)
                //     {
                //         foreach ($detailSpeedArray as & $speed) {
                //             if($this->base->vn <= 1500)
                //             {
                //                 $speed <= 120 && $speed = round($speed*60, 2);
                //             }
                //             else
                //             {
                //                 $speed > 120 && $speed = round($speed/60, 2);
                //             }
                //         }
                //     }
                //     else
                //     {
                //         foreach ($detailSpeedArray as & $speed) {
                //             $speed >= 120 && $speed = round($speed/60, 2);
                //         }
                //     }
                //     $v['detail_speed'] = json_encode($detailSpeedArray);
                // }
                $medal = !empty($v['medal']) ? json_decode($v['medal'], TRUE) : array();
                if(!empty($medal) && (($this->base->vn > 1850 && $this->base->projectId == 1) || $this->base->projectId == 2))
                {
                    $temMedal =array();
                    foreach ($medal as $medal_id) {
                        $medalInfo = $this->base->load('medal')->getMedalInfo($medal_id);
                        if($medalInfo)
                        {
                            $temMedal[] = array('medal_id' => $medal_id,
                                                 'medal_name'   => $medalInfo['medal_name'],
                                                 'word'   => $medalInfo['word'],
                                                 'isCustom'   => $medalInfo['isCustom']
                                );
                        }
                    }
                    $v['medal'] = $temMedal;
                }
                unset($v['is_delete'], $v['version'], $v['cid']);
                // 跑步所在月份，
                $v['month'] = date("Ym", $v['updatetime']);
                $m = round($v['mileage'], 2);
                $t = common::sec2time($v['elapsedtime']);

                $coordinate = @base64_decode($v['coordinate']);
                $uncompress = $coordinate ? @gzuncompress($coordinate) : FALSE;
                !$uncompress && $uncompress = @gzuncompress($v['coordinate']);
                $v['coordinate'] = !$uncompress ? $v['coordinate'] : stripslashes($uncompress);
                $v['coordinate'] = trim($v['coordinate'], '"');
                $v['coordinate'] = $v['coordinate'] ? json_decode($v['coordinate'], true) : array();

                $v['point_coordinate'] = stripslashes($v['point_coordinate']);
                $v['point_coordinate'] = trim($v['point_coordinate'], '"');
                $v['point_coordinate'] = $v['point_coordinate'] ? json_decode($v['point_coordinate'], true) : array();
                $data = $this->reCoordinate($v['coordinate']);
                $v['coordinate'] = $data;
                $v['detail_speed'] = stripslashes($v['detail_speed']);
                $v['detail_speed'] = trim($v['detail_speed'], '"');
                $v['detail_speed'] = $v['detail_speed'] ? json_decode($v['detail_speed'], true) : array();
                $v['southWestPoint'] = stripslashes($v['southWestPoint']);
                $v['southWestPoint'] = trim($v['southWestPoint'], '"');
                $v['southWestPoint'] = $v['southWestPoint'] ? json_decode($v['southWestPoint'], true) : array();
                $v['northEastPoint'] = stripslashes($v['northEastPoint']);
                $v['northEastPoint'] = trim($v['northEastPoint'], '"');
                $v['northEastPoint'] = $v['northEastPoint'] ? json_decode($v['northEastPoint'], true) : array();

                $v['detail_speed_curve'] = $v['detail_speed_curve'] ? json_decode($v['detail_speed_curve'], TRUE) : [];
                $v['detail_elevation_curve'] = $v['detail_elevation_curve'] ? json_decode($v['detail_elevation_curve'], TRUE) : [];
                $v['detail_elevation_fold'] = $v['detail_elevation_fold'] ? json_decode($v['detail_elevation_fold'], TRUE) : [];
                $v['detail_footsteps_curve'] = $v['detail_footsteps_curve'] ? json_decode($v['detail_footsteps_curve'], TRUE) : [];
                $v['detail_footsteps_fold'] = $v['detail_footsteps_fold'] ? json_decode($v['detail_footsteps_fold'], TRUE) : [];

                $v['desc'] = '你跑了' . $m . '公里用时' . $t;
                unset($result[$k]['uid'], $result[$k]['addtime'], $result[$k]['is_delete']);
                
            }
        }
        return $result;
    }

    /**
     * 获取指定客户端最新的跑步数据
     * @param int $uid
     * @param int $num
     * @return array
     */
    public function getClientRunData($uid, $page = 1, $did, $direc, $offset, $beginTime = NULL, $endTime = NULL)
    {
        $sql = "select d.*,de.coordinate,de.detail_speed_curve,de.detail_elevation,de.detail_elevation_curve,de.detail_footsteps,de.detail_footsteps_curve,de.detail_stride,de.detail_elevation_fold,de.detail_footsteps_fold from r_data as d left join r_data_ext de on d.did=de.did where uid='{$uid}' and is_delete = 0 ";

        if($beginTime)
        {
            $beginTime = intval($beginTime);
            $beginTime && $sql .= " and updatetime>={$beginTime} ";
        }

        if($endTime)
        {
            $endTime = intval($endTime);
            $endTime && $sql .= " and updatetime<{$endTime} ";
        }

        if($did > 0)
        {
            $sql .= 'and d.did ';
            $sql .= $direc == 'prev'? '>' : '<';
            $sql .= "{$did} order by d.did DESC limit {$offset}";
        }
        else
        {
            $start = ($page - 1) * $offset;
            $sql .= "order by d.did desc limit {$start}, {$offset}";
        }
        $result = $this->db->getAll($sql);
        !$result && $result = array();

        return $result;
    }

    /**
     * 获取指定游客的历史跑步数据 (1.0版本时才调用)
     * @param int $uid
     * @return array
     */
    public function getVisitorRunHistoryData($vid, $page = 1, $offset = 20)
    {
        $result = array();
        $total = array('mileage' => 0, 'elapsedtime' => 0);
        $data = $this->getVisitorRunData($vid, $page, $offset);
        if ($data)
        {
            $old_uid = $this->db->getone("select old_uid from r_visitor where vid = '{$vid}' limit 1");
            foreach ($data as $k => & $v)
            {
                if($old_uid > 1)
                {
                    $data[$k]['record_img'] = common::realUrl($v['record_img']);
                    $data[$k]['record_img_thumb'] = str_replace('/record/', '/record/thumb/', $data[$k]['record_img']);
                }

                $m = round($v['mileage'], 2);
                $t = common::sec2time($v['elapsedtime']);
                $total['mileage'] += $m;
                $total['elapsedtime'] += $t;
                $coordinate = @base64_decode($v['coordinate']);
                $uncompress = $coordinate ? @gzuncompress($coordinate) : FALSE;
                !$uncompress && $uncompress = @gzuncompress($v['coordinate']);
                $v['coordinate'] = !$uncompress ? $v['coordinate'] : stripslashes($uncompress);
                $data[$k]['coordinate'] = !empty($v['coordinate']) ? json_decode($v['coordinate'], TRUE) : '';
                $data[$k]['coordinate'] = $this->reCoordinate($v['coordinate']);
                $data[$k]['desc'] = '你跑了' . $m . '公里用时' . $t;
                unset($data[$k]['vid'], $data[$k]['addtime']);
            }
        }
        $result = array('total' => $total, 'data' => $data);
        return $result;
    }

    /**
     * 获取指定客户端最新的跑步数据
     * @param int $uid
     * @param int $num
     * @return array
     */
    public function getVisitorRunData($vid, $page = 1, $offset = 20)
    {
        $start = ($page - 1) * $offset;
        $data = $this->db->getAll("select * from r_visitor_data where vid='{$vid}' and is_delete = 0 order by addtime desc limit {$start}, {$offset}");
        !$data && $data = array();

        return $data;
    }

    /**
     * 获取跑步里程排行榜前100名用户信息
     * @param int $topNum
     * @return array
     */
    public function getMileageStandingTopInfo($topNum)
    {
    
        $topInfo = $this->redis->get(REDIS_PREFIX.'StandingsTopInfo');
        if(!$topInfo)
        {
            $result = $this->updateMileageStandingsInfo($topNum);
        }
        else
        {
            $result = json_decode($topInfo, true);
        }

        !$result && $result = array();

        return $result;
    }
    /**
     * 更新用户跑步排行总榜
     * @param int $uid
     * @return int
     */
    public function updateMileageStandingsInfo($topNum = 100)
    {
        $topNum = intval($topNum);

        $result = array();
        $uids = $this->redis->zrevrange(REDIS_PREFIX . 'StandingsMileage', 0, $topNum - 1);
        if($uids)
        {
            $this->base->load('client');
            foreach ($uids as $k => $v)
            {
                $userInfo = $_ENV['client']->getUserInfo($v);
                if(empty($userInfo))
                {
                    continue;
                }
                
                $result[] = array(
                    'uid' => $v,
                    'rank' => $k + 1,
                    'nickname' => $userInfo['nickname'],
                    'level' => isset($userInfo['level']) ? $userInfo['level'] : common::getLevel($userInfo['total_mileage']),
                    'header' => $userInfo['header'],
                    'gender' => $userInfo['gender'],
                    'total_mileage' => sprintf("%.2f", $userInfo['total_mileage']),
                    'total_rate' => $userInfo['total_rate'],
                );
            }


            $this->redis->set(REDIS_PREFIX.'StandingsTopInfo', json_encode($result));
        }

        return $result;
    }
    /**
     * 获取指定客户端的跑步里程排名
     * @param int $uid
     * @return int
     */
    private function getClientMileageStandingsRank($uid)
    {
        $rank = $this->redis->zrevrank(REDIS_PREFIX . 'StandingsMileage', $uid);
        $rank = $rank !== FALSE ? $rank + 1 : 0;

        return intval($rank);
    }
    /*
    * 生成跑步排行榜数据
    */
    public function createStandings()
    {
        $this->redis->del(REDIS_PREFIX . 'StandingsMileage');
        $u_data = $this->db->getall("select uid, total_mileage from r_user order by total_mileage DESC, uid ASC");
        if($u_data)
        {
            foreach($u_data as $user)
            {
                if($user['uid'])
                {
                    $this->setClientMileageStandingsRank($user['uid'], $user['total_mileage']);
                }
            }
        }
        return TRUE;
    }
    /**
     * 获取指定名次与前一名总里程的差
     * @param int $rank
     * @return int
     */
    private function getClientMileageGap($rank = false)
    {
        $gapStr = '';
        if ($rank === 1) // 第一名
        {
            $gapStr = '你的下一个对手就是你自己！';
        }
        elseif($rank > 1 && $rank <= 15000)  // 2-15000名
        {
            $gapStr = $rank <= 5000 ? '您当前的总排行为' . $rank . '名' : '快快奔跑吧，您的总排行已经在5000名以后了';
        }
        else if($rank > 15000)
        {
            $gapStr = '努力奔跑就能榜上有名！';
        }
        else
        {
            $gapStr = '亲，快去跑步确定江湖地位吧！';
        }

        return $gapStr;
    }

    /**
     * 设置指定客户端的跑步里程排名
     * @param int $uid
     * @param float $mileage
     * @return boolean
     */
    public function setClientMileageStandingsRank($uid, $mileage)
    {
        return $this->redis->zadd(REDIS_PREFIX . 'StandingsMileage', $mileage, $uid) !== FALSE;
    }

    /**
     * 删除指定uid的排名
     * @param type $uid
     * @return type
     */
    public function delClientMileageStandingsRank($uid)
    {
        return $this->redis->zrem(REDIS_PREFIX . 'StandingsMileage', $uid) !== FALSE;
    }
    /**
     * 里程勋章的随机提示：“您再跑XX公里将升级运动里程勋章！请再接再厉！”  （ 公里数保留1位有效数字）
     * 跑步次数勋章的随机提示：“您再跑步XX次将获得下一枚运动次数勋章！爱跑为您加油！” （次数为整数）
     * 捐款金额勋章随机提示： “您的慈善金额达到XX元后爱跑将为您升级爱心勋章！” （元为整数）
     * 等级：“您再跑步XX小时可升至XX级哦a！”  （小时数保留1位有效数字）
     * @param type $mileage
     * @param type $donation
     */
    public function getTips($mileage, $donation, $rate, $time)
    {
        $typeArr = array('mileage', 'donation', 'rate', 'time');
        $rand = rand(0, 3);
        $word = "";

        switch ($typeArr[$rand]) {
            case 'mileage':
                foreach (common::$medalArr['mileage'] as $v)
                {
                    //var_dump($v);
                    if ($mileage < 10)
                    {
                        $away = 10 - $mileage;
                        $word = "您再跑{$away}公里将升级运动里程勋章！请再接再厉！";
                        break;
                    }
                    if ($mileage >= $v['min'] && $mileage < $v['max'])
                    {
                        $away = $v['max'] - $mileage;
                        $word = "您再跑{$away}公里将升级运动里程勋章！请再接再厉！";
                        $v['max'] == PHP_INT_MAX && $word = "mileage";
                    }
                }
                break;
            case 'donation':
                foreach (common::$medalArr['donation'] as $v)
                {
                    if ($donation < 5)
                    {
                        $word = "您的慈善金额达到5元后爱跑将为您升级爱心勋章！";
                        break;
                    }

                    if ($donation >= $v['min'] && $donation < $v['max'])
                    {
                        $word = "您的慈善金额达到{$v['max']}元后爱跑将为您升级爱心勋章！";
                        $v['max'] == PHP_INT_MAX && $word = "donation";
                    }
                }
                break;
            case 'rate':
                foreach (common::$medalArr['rate'] as $v)
                {
                    if ($rate == 0)
                    {
                        $word = "您再跑步1次将获得下一枚运动次数勋章！爱跑为您加油！";
                        break;
                    }
                    if ($rate >= $v['min'] && $rate < $v['max'])
                    {
                        $away = $v['max'] - $rate;
                        $word = "您再跑步{$away}次将获得下一枚运动次数勋章！爱跑为您加油！";
                        $v['max'] == PHP_INT_MAX && $word = "rate";
                    }
                }
                break;
            case 'time':
                $levelArr = array(
                    '5' => 5 * 2 * 3600,
                    '10' => 5 * 2 * 3600 + 5 * 4 * 3600,
                );
                if ($time < $levelArr['5'])
                {
                    $next = floor($time / (3600 * 2)) + 1;
                    $away = $next * 3600 * 2 - $time;
                } elseif ($time >= $levelArr['5'] && ($time < $levelArr['10']))
                {
                    $next = floor(($time - $levelArr['5']) / (3600 * 4) + 5) + 1;
                    $away = $next * 3600 * 4 - $time;
                } elseif ($time >= $levelArr['10'])
                {
                    $next = floor(($time - $levelArr['10']) / (3600 * 6) + 10) + 1;
                    $away = $next * 3600 * 6 - $time;
                }
                $hour = round($away / 3600, 1);
                ($hour == 0 && $next == 1) && $hour = 2; //默认再跑两小时就可以升1级
                $word = "您再跑步{$hour}小时可升至{$next}级哦！";
                break;
        }

        return $word;
    }

    /**
     * 上传跑步用户记录图片
     * @param type $inputname
     */
    public function uploadRecordImg($inputName)
    {
        $day = date('Ymd');
        $path = 'u/' . $day . '/record/';
        $result = $this->base->uploadFile($inputName, $path, 5*1024*1024);

        if($result)
        {
            $dir = FILE . '../web/static/';
            !file_exists($dir . $path . 'thumb') && mkdir($dir . $path . 'thumb');
            $thumb = str_replace($path, $path . 'thumb/', $result);
            Image::thumb($dir . $result, $dir . $thumb);
        }

        return $result;
    }

    public function uploadShareImg($inputName)
    {
        require FILE . 'lib/image.class.php';
        $day = date('Ymd');
        $path = 'u/' . $day . '/share/';
        $result = $this->base->uploadFile($inputName, $path);

        // $dir = FILE . '../web/static/';
        // !file_exists($dir . $path . 'thumb') && mkdir($dir . $path . 'thumb');
        // $thumb = str_replace($path, $path . 'thumb/', $result);
        // Image::thumb($dir . $result, $dir . $thumb);

        return $result;
    }
    /**
     * 记录用户跑步等级变动
     * @param int $uid
     * @param int $level
     * @param float $mileage
     * @param string $words
     */
    public function runLevelUpRecord($uid, $level, $mileage, $words = '', $add_time=0)
    {
        if(empty($words)) {
            if($level >0) {
                $words =  $this->base->config['runLevelUpWords'];
            }else
            {
                $words =  $this->base->config['runLevelDownWords'];
            }
        }
        $level < 0 && $level = 0-$level;
        empty($add_time) && $add_time = time();
        if(!empty($uid) && !empty($level) && !empty($mileage))
        {
            $title = common::$runLevel[$level]['title'];
            $description = @sprintf($words, $mileage, $title);
            $data = compact('uid', 'level', 'mileage', 'description', 'add_time');
            $this->db->insertRowTable('r_runLevelRecord', $data);
        }
        return;
    }
    /**
     * 更新好友排行榜信息
     * @param int $uid
     * @param float $mileage
     * @param int $updatetime
     * @param return
     */
    public function updateUserFStandings($uid, $mileage=0, $addtime=0)
    {
        $randWeekRKey = REDIS_PREFIX .'friendMilStangdsweek'.date("W").'_';
        $randMonthRKey = REDIS_PREFIX .'friendMilStangdsmonth'.date("n").'_';
        $uids =  $this->redis->ZREVRANGEBYSCORE(REDIS_PREFIX.'Friends_'.$uid, '+inf', '-inf');

        $addtime = empty($addtime) ? time() : $addtime;
        $updateWeek = (strtotime("next Monday")-$addtime) > 7*86400 ? 0 : 1;
        $updateMonth = (date("Y").'-'.date("m").'-1') > $addtime ? 0 : 1;

        // 更新本周（月）用户跑步数据
        $weekData = $this->base->load('client')->getUserFrRunData($uid, 'week',true);
        $monthData = $this->base->load('client')->getUserFrRunData($uid, 'month',true);
        // 更新好友排行中该用户的数据
        if($uids)
        {
            foreach ($uids as $key => $f_uid) {
                $updateWeek && $this->redis->del($randWeekRKey.$f_uid);
                $updateMonth && $this->redis->del($randMonthRKey.$f_uid);
            }
            $updateWeek && $this->redis->del($randWeekRKey.$uid);
            $updateMonth && $this->redis->del($randMonthRKey.$uid);
        }
        return;
    }
    /**
     * 获取用户跑步步数
     * @param int $uid
     * @param float $mileage
     * @param int $elapsedtime
     * @param return int $steps
     */
    public function getRunSteps($uid, $mileage=0, $elapsedtime=0)
    {
        $steps = 0;
        if(!empty($mileage) && !empty($uid))
        {
            $pace = intval($elapsedtime/$mileage/60);
            $height = $this->redis->hget(REDIS_PREFIX.'UserInfo_'.$uid, 'height');
            !$height && $height = 170;
            $stride = (1- intval($pace/2)/10); // 步幅系数
            $stride < 0.5 && $stride = 0.5;
            $steps = intval($mileage*100/$stride/$height);
        }
        return $steps;
    }

    /**
    * 向QQ健康中心发送用户跑步数据
    * @param int $uid
    * @param float $distance
    * @param int $duration
    * @param return int $steps
    */
    public function sendQqHealthData($runDataQq)
    {
        extract($runDataQq);
        if(empty($access_token) ||empty($openid) ||empty($uid) ||empty($time))
        {
            return ;
        }

        $dayStart = strtotime(date("Y-m-d", $time));

        $dayEnd = $dayStart + 86400;
        $runData = $this->db->getRow("select sum(mileage) as distance, sum(elapsedtime) as duration, sum(calorie) as calories from r_data where uid = '{$uid}' and updatetime >= '{$dayStart}' and updatetime <= '{$dayEnd}'");
        if(empty($runData['distance']) ||empty($runData['duration']) ||empty($runData['calories']))
        {
            return ;
        }
        $url = 'https://openmobile.qq.com/v3/health/report_running';
        $postData['pf'] = 'qzone';
        $postData['oauth_consumer_key'] = '1101378442';
        $postData['openid'] = $openid;
        $postData['access_token'] = $access_token;
        $postData['time'] = $time;
        $postData['distance'] = intval($runData['distance'] * 1000);
        $postData['duration'] = intval($runData['duration']);
        $postData['calories'] = intval($runData['calories']);
        $postData['steps'] = $this->getRunSteps($uid, $postData['distance'], $postData['duration']);
        $postData['speed'] = round($postData['distance'] / $postData['duration'], 2);
        $rel = common::getContents($url, $postData, 3, 'POST');

        return $rel;
     }
    /**
    *  保存QQ健康接收失败的数据 
    * @param array $qqHealthData
    * @param return boolen
    */
    public function qqHealthFail($qqHealthData)
    {
        $result = FALSE;

        if(!isset($qqHealthData['access_token']) || !isset($qqHealthData['openid']) || !isset($qqHealthData['uid']) || !isset($qqHealthData['date']))
        {
            return $result;
        }

        $redisKey = REDIS_PREFIX.'QqHealthFail';

        $result = $this->redis->LPUSH($redisKey, json_encode($qqHealthData));
        return;
    }
    /**
    *  重新发送QQ健康接收失败的数据 
    * @param 
    * @param return boolen
    */
    public function resendQqHealthData()
    {
        $redisKey = REDIS_PREFIX.'QqHealthFail';

        if(!$this->redis->LLEN($redisKey))
        {
            return FALSE;
        }
        $qqHealthData = $this->redis->LPOP($redisKey);

        if($qqHealthData && common::is_json($qqHealthData))
        {
            $qqHealthData = json_decode($qqHealthData, TRUE);
            if(!empty($qqHealthData))
            {
                $this->sendQqHealthData($qqHealthData);
            }
        }

        
        return TRUE;
    }
    /*
     * 添加用户日跑步数据
    */
    public function addDayRunData($uid, $data)
    {
        $result = false;
        extract($data);
        $delete = (isset($delete) && $delete === true) ? true : false;
        if(empty($uid)||!isset($mileage)||!isset($elapsedtime)||!isset($calorie)||!isset($updatetime))
        {
            return $result;
        }
        $mileage = round($mileage, 2);
        $elapsedtime = intval($elapsedtime);
        $calorie = intval($calorie);
        $date = date("Ymd", $updatetime);
        $o_data = $this->db->getRow("select id,mileage from r_data_day where uid = '{$uid}' and date = '{$date}'");
        if($o_data)
        {
            $total_rate = $delete ? 'total_rate -1' : 'total_rate +1';
            $sql = $o_data['mileage']
                ? "update r_data_day set mileage = mileage+{$mileage},elapsedtime=elapsedtime+{$elapsedtime},calorie=calorie+{$calorie},total_rate={$total_rate} where uid = '{$uid}' and date = '{$date}'"
                : "update r_data_day set mileage = {$mileage},elapsedtime={$elapsedtime},calorie={$calorie},total_rate=1 where uid = '{$uid}' and date = '{$date}'";
            $result = $this->db->update($sql);
        }
        else
        {
            $total_rate = 1;
            $insertData = compact('uid','date','mileage','elapsedtime','calorie','total_rate');
            $delete === false && $result = $this->db->insertRowTable('r_data_day', $insertData);
        }
        return $result;
    }
    
    /*
     * 统计用户日跑步数据
     */
    public function updateDayRunData($uid,$timestamp){
        $date = date('Ymd',$timestamp);
        $stime = strtotime(date('Y-m-d 00:00:00',$timestamp));
        $etime = strtotime(date('Y-m-d 24:00:00',$timestamp));
        $sql = "select mileage,elapsedtime,calorie from r_data where uid=$uid and updatetime between $stime and $etime and overSpeed=0 and is_delete=0";
        
        $mileage = 0;
        $elapsedtime = 0;
        $calorie = 0;
        $total_rate = 0;
        foreach($this->db->getAll($sql) as $row){
            $mileage += $row['mileage'];
            $elapsedtime += $row['elapsedtime'];
            $calorie += $row['calorie'];
            $total_rate += 1;
        }
        $o_data = $this->db->getRow("select id from r_data_day where uid = '{$uid}' and date = '{$date}'");
        if($o_data){
            $sql = "update r_data_day set mileage={$mileage},elapsedtime={$elapsedtime},calorie={$calorie},total_rate={$total_rate} where uid='{$uid}' and date='{$date}' limit 1";
            $result = $this->db->update($sql);
        }else{
            $result = $this->db->insertRowTable('r_data_day',compact('uid','date','mileage','elapsedtime','calorie','total_rate'));
        }
        return $result;
    }
    
    /*
     * 获取用户跑步数据统计信息
    */
    public function getRunStatistics($uid, $weeks=11)
    {
        $data = array();
        $week_max = "0.00";
        $weeks = intval($weeks);
        for($i=$weeks-1; $i>=0; $i--)
        {
            $day = date("Y-m-d", strtotime("-$i weeks"));
            $line = strtotime("$day next Monday");
            $MonDate = $line - 7*86400;
            $SunDate = $line - 86400;
            $weekMileage = "0";
            $weekRunDays = '0';
            $day_max = '0';
            $startDate = date("Ymd", $MonDate);
            $endDate = date("Ymd", $line);
            $details = array();
            $runDataTemp = $this->db->getAll("select updatetime as date, mileage from r_data where uid='{$uid}' and updatetime >= '{$MonDate}' and updatetime <= '{$line}' and is_delete = 0 and overSpeed = 0");

            if(!empty($runDataTemp))  //合并一周每天
            {
                foreach ($runDataTemp as $key => $value) {
                    $value['date'] = strtotime(date("Ymd",$value['date']));
                    $runDataTemp[$value['date']][]= $value;
                    unset($runDataTemp[$key]);
                }
            }
            for($j=7; $j>0; $j--)
            {
                $date = strtotime(date("Ymd",$line - $j*86400));
                
                if(isset($runDataTemp[$date]))
                {
                    $day_sum = 0;
                     foreach ($runDataTemp[$date] as $key => $value) {
                            $weekMileage += $value['mileage']; //周总里程
                            $day_sum+=$value['mileage'];
                            unset($runDataTemp[$date][$key]);  
                     }

                    $runDataTemp[$date]['date'] = $date;
                    $runDataTemp[$date]['mileage']=$day_sum;
                    $day_sum >$day_max&&$day_max=$day_sum;   //当周最大日跑量
                    $runDataTemp[$date]['mileage'] > 0 && $weekRunDays +=1; //该周跑步天数
                    $details[] = $runDataTemp[$date];
                }
              
                else
                {
                    $details[] = array('date' => $line - $j*86400, 'mileage' => "0.00");
                }
            }
            $week_max < $weekMileage && $week_max = $weekMileage;
            $weekMileage = strval($weekMileage);
            $weekRunDays = strval($weekRunDays);
            $week_max = strval($week_max);
            $data[] = compact('MonDate','SunDate','weekMileage','weekRunDays','day_max','details');
        }
        return compact('data', 'week_max');
    }
    /*
     * 累加跑步数据
    */
    public function cumRunData($uid, $addData)
    {
        $result = false;
        $colArray = array('mileage','elapsedtime','calorie');
        if(!is_array($addData) || $uid < 1)
        {
            return $result;
        }
        foreach ($colArray as $name) {
           if(!isset($addData[$name]))
           {
                return $result;
           }
        }
        $colArray[] = 'rate';
        $addData['rate'] = 1;
        foreach ($colArray as $name) {
            $colName = 'total_'.$name;
            $value = $addData[$name];
            if($this->db->update("update r_user set {$colName} = {$colName} + {$value} where uid = '{$uid}'") != false)
            {
                if($name == 'mileage')
                {
                    $total_mileage = $this->db->getOne("select sum(mileage) from r_data where uid ='{$uid}' and is_delete = '0' and overspeed = 0");
                    $value = round($total_mileage, 2);
                    $this->redis->HSET(REDIS_PREFIX.'UserInfo_'.$uid, $colName, $value);
                }
                else
                {
                    $this->redis->HINCRBY(REDIS_PREFIX.'UserInfo_'.$uid, $colName, $value);
                }
            }
        }
        return true;
    }
    /*
     * 用户为跑步记录点赞
    */
    public function likeRunRecord($uid, $did, $gid)
    {
        $result = false;
        if(empty($uid) || empty($did) || empty($gid))
        {
            return $result;
        }
        if($this->redis->ZSCORE(REDIS_PREFIX.'RunLike_'.$gid.'_'.$did, $uid))
        {
          return $result;
        }
        $data = array('did' => $did,
                      'uid' => $uid,
                      'gid' => $gid
                    );
        if($this->db->insertRowTable('r_run_like', $data))
        {
            $this->db->update("update r_group_run set likes = likes +1 where did = '{$did}' and gid = '{$gid}'");
            $this->redis->ZADD(REDIS_PREFIX.'RunLike_'.$gid.'_'.$did, time(), $uid);
            $result = true;
        }
        return $result;
    }
    /*
     * 跑步记录点赞数
    */
    public function getRunRecordLikes($did, $gid)
    {
        $result = '0';
        if(empty($did) || empty($gid))
        {
            return $result;
        }
        $result = $this->redis->ZCARD(REDIS_PREFIX.'RunLike_'.$gid.'_'.$did);
        if($result === 0)
        {
            $result = $this->db->getOne("select likes from r_group_run where did = '{$did}' and gid = '{$gid}'");
        }
        return intval($result). '';
    }
    /**
     * 检查日志文件是否合法
     * @param str $num 加密参数
     * @param str $inputname 日志参数名
     * @param int $limit 日志大小限制(Kb)
     * @return boolen $result
    */
    public function checkLog($num, $key, $inputname = 'log', $limit = 1024)
    {
        $result = false;
        if(gettype($num) == 'string' && preg_match("/^[0-9a-zA-Z]{10}$/",$num) && isset($_FILES[$inputname]))
        {
            if($_FILES[$inputname]['size']/1024 <= 1024 && substr($_FILES[$inputname]['name'], -4) === '.log')
            {
                if(md5($num.md5_file($_FILES[$inputname]['tmp_name']).'SHENGZHIJIAXINYINGQUBAIFUMEI***') === $key)
                {
                    $result = true;
                }
            }
        }
        return $result;
    }
    /**
     * 保存日志
     * @param str $inputname 日志参数名
    */
    public function saveLog($num, $key, $inputname = 'log')
    {
        $result = false;
        if($this->checkLog($num, $key, $inputname))
        {
            $path = $this->base->config['log-dir'].'runlog/';
            !file_exists($path) && mkdir($path);
            $logName = date("Ymd");
            $logName .= $this->base->uid ? 'U'.$this->base->uid : 'V'.$this->base->vid;
            $logName .= '-'.common::getHashStr(6).'.'.end(explode('.', $_FILES[$inputname]['name']));
            if(@move_uploaded_file($_FILES[$inputname]['tmp_name'], $path.$logName))
            {
                $result = true;
            }
        }
        return $result;
    }
    /**
     *  保存用户跑步记录的order_id
     * @param int $uid 用户id
     * @param int $order_id  跑步记录的 order_id
    */
    public function setOrderId($uid, $order_id)
    {
        return $this->redis->hset(REDIS_PREFIX . 'runDataOrder_' . $uid, $order_id, 1) !== false;
    }
    /**
     *  验证 order_id 对应的跑步记录是否已上传
     * @param int $uid 用户id
     * @param int $order_id  跑步记录的 order_id
     * @return boolen TRUE 为能过验证, 否则表示跑步记录已上传
    */
    public function checkOrderId($uid, $order_id)
    {
        return $this->redis->hexists(REDIS_PREFIX . 'runDataOrder_' . $uid, $order_id) == false;
    }
    /**
     * 跑步累计数据
     * 已经不再使用！！！！！！！！！！
     */
    public function updateUserBestRunRecord($uid, $userInfo = array(), $runData = array())
    {
        $result = FALSE;

        if(!$uid || empty($userInfo) || empty($runData))
        {
            return $result;
        }
        // 用户新记录
        $newRecord = array();

        // 更新用户最佳记录
        $runData['mileage'] > $userInfo['max_mileage'] && $newRecord['max_mileage'] = $runData['mileage'];
        $runData['elapsedtime'] > $userInfo['max_elapsedtime'] && $newRecord['max_elapsedtime'] = $runData['elapsedtime'];
        $runData['five_time'] > 0 && $runData['five_time'] < $userInfo['max_five_time'] && $newRecord['max_five_time'] = $runData['five_time'];
        $runData['ten_time'] > 0 && $runData['ten_time'] < $userInfo['max_ten_time'] && $newRecord['max_ten_time'] = $runData['ten_time'];
        $runData['half_mtime'] > 0 && $runData['half_mtime'] < $userInfo['max_half_mtime'] && $newRecord['max_half_mtime'] = $runData['half_mtime'];
        $runData['mara_time'] > 0 && $runData['mara_time'] < $userInfo['max_mara_time'] && $newRecord['max_mara_time'] = $runData['mara_time'];

        if(empty($newRecord))
        {
            $this->base->load('client')->setUserInfo($uid, $newRecord);
        }

        $result = TRUE;
        return $result;
    }
    /**
     *  更新用户跑步等级
     * @param int $uid 用户id
     */
    public function updateUserRunLevel($uid, array $userInfo, $mileage = 0, $updatetime = 0)
    {
        if(!$uid || !isset($userInfo['level']) || !isset($userInfo['mileage']) || !$updatetime)
        {
            return FALSE;
        }

        $total_mileage = round($userInfo['mileage'] + $mileage, 2);
        $nowLevel = common::getLevel($total_mileage);

        if($nowLevel > $userInfo['level'])
        {
            $this->base->load('client')->setUserInfo($uid, array('level' => $nowLevel));
            $this->runLevelUpRecord($uid, $nowLevel, $total_mileage, '', $updatetime);
        }

        return TRUE;
    }
    /**
     * 更新用户最后一次跑步描述信息
     * @param int $uid
     * @param array $runData 最新跑步数据
     * @return boolen
    */
    public function updateLatestRun($uid, $runData = array())
    {
        $result = FALSE;

        if(!$uid || empty($runData) || !isset($runData['mileage']) || !isset($runData['elapsedtime']) || !isset($runData['city']) || !isset($runData['calorie']) || !isset($runData['updatetime']))
        {
            return $result;
        }

        $redisKey = REDIS_PREFIX . 'latestRun_'.$uid;

        //$latestRunWords = $this->base->config['latestRunWords'];
        $city = $runData['city'] == '未知' ? '一个谁也不知道的地方': $runData['city'];
        
        //$timediff = common::timediff(time() - $runData['updatetime'],'run');
        //$mileage = $runData['mileage']. 'km';
        //$result['description'] = sprintf($latestRunWords, $timediff, $mileage);
        $result['run_time'] = $runData['updatetime'];
        $result['description'] = $runData['mileage'];
            
        $this->redis->hmset(REDIS_PREFIX . 'latestRun_' .$uid, $result);

        return $result;
    }
    /**
     * 记录跑步记录中的qq健康信息
     * @param int $did
     * @param array $qqHealthInfo    qq_openid、qq_acc_token
     * @return boolen
    */
    public function setQqHealthInfo($did, $qq_openid, $qq_acc_token)
    {
        $redisKey = REDIS_PREFIX.'QqhealthInfo';

        if($qq_openid && $qq_acc_token)
        {
            $qqHealthInfo = compact('qq_openid', 'qq_acc_token');

            return $this->redis->hset($redisKey, $did, json_encode($qqHealthInfo)) != FALSE;
        }

        return FALSE;
    }
    /**
     * 获取跑步记录中的qq健康信息
     * @param int $did
     * @return array $qqHealthInfo    qq_openid、qq_acc_token
    */
    public function getQqHealthInfo($did)
    {
        $result = array();
        $redisKey = REDIS_PREFIX.'QqhealthInfo';

        $qqHealthInfo = $this->redis->hget($redisKey, $did);

        if(common::is_json($qqHealthInfo))
        {
            $result = json_decode($qqHealthInfo, TRUE);
        }
        
        empty($result) && $result = array();

        return $result;
    }
    /**
     * 将某跑步数据加入到待处理队列中
     * @param int $did
     * @return
    */
    public function pushPendingRunList($did)
    {
        $redisKey = REDIS_PREFIX.'PendingRunData';
        
        $this->redis->LPUSH($redisKey, $did);
        
        $redisKey = REDIS_PREFIX.'YNPendingRunData';
        $this->redis->LPUSH($redisKey, $did);
    }
    /**
     * 从待处理跑步记录队列中取出一条记录
     * @param i
     * @return
    */
    public function popPendingRunData()
    {
        $redisKey = REDIS_PREFIX.'PendingRunData';

        $did = $this->redis->RPOP($redisKey);

        return $did;
    }

    /**
     * 检测跑步数据是否异常
     * @param 
     * 规则：速度：整条记录中，【平均时速不大于20km/h】 且【配速不能有多于2个公里是小于 3min/km】。超出范围即为异常数据。
     * 规则：里程：单条记录的里程不超过105km，或当天累计跑步记录的总里3：时间异常程不超过105km（超过的那条起记为异常数据）
     * 规则：时间：当前要提交的跑步记录  【跑步开始时间 】小于 前一条有效记录的  【开始时间+跑步花费时间】。（误差允许5分钟范围内）
     * @return int 0:正常， 1：速度异常， 2：里程异常， 3:时间异常
    */
    public function checkCheatRun($uid,$mileage, $elapsedtime, $updatetime, $detail_speed)
    {
        // 速度
    
        $averageSpeed = round(($mileage * 3600) / $elapsedtime, 2);

        if($averageSpeed > 20)
        {
            return 1;
        }

        $speedTimes = 0;  // 异常配速个数
        // if(!common::is_json($detail_speed))
        // {
        //     return 1;
        // }
        // foreach (json_decode($detail_speed) as $v)
        // {
        //     $v <= 2 && $speedTimes += 1;

        //         if($speedTimes >= 2)
        //         {
        //         return 1;
        //         }
        //     }
        // }
        // 里程
        $thisDayMileage = $this->usertotalMileageByDay($uid, date("Y-m-d", $updatetime));
        if($mileage > 105 || ($mileage + $thisDayMileage) > 105)
        {
            return 2;
        }

        // 时间
        $runDataSta = $updatetime - $elapsedtime;
        $runDataEnd = $updatetime;
        $prevEffectiveRun = $this->getPrevEffectiveRun($uid,$runDataSta);
        $nextEffectiveRun = $this->getNextEffectiveRun($uid,$runDataSta);
        
        if(!empty($prevEffectiveRun))
        {
            $preRunSta = $prevEffectiveRun['updatetime']-$prevEffectiveRun['elapsedtime'];
            $preRunEnd = $prevEffectiveRun['updatetime'];
           
            $flag = $this->timeSuperposition($runDataSta,$runDataEnd,$preRunSta,$preRunEnd);
            if($flag)
            {
                return 3;
            }
        }

        if(!empty($nextEffectiveRun))
        {
            $nextRunSta = $nextEffectiveRun['updatetime']-$nextEffectiveRun['elapsedtime'];
            $nextRunEnd = $nextEffectiveRun['updatetime'];
            $flag = $this->timeSuperposition($runDataSta,$runDataEnd,$nextRunSta,$nextRunEnd);
            if($flag)
            {
                return 3;
            }
        }
        return 0;
    }

    /**
     * 检测游客跑步数据是否异常
     * @param 
     * 规则：速度：整条记录中，【平均时速不大于20km/h】 且【配速不能有多于2个公里是小于 3min/km】。超出范围即为异常数据。
     * 规则：里程：单条记录的里程不超过105km，或当天累计跑步记录的总里3：时间异常程不超过105km（超过的那条起记为异常数据）
     * 规则：时间：当前要提交的跑步记录  【跑步开始时间 】小于 前一条有效记录的  【开始时间+跑步花费时间】。（误差允许5分钟范围内）
     * @return int 0:正常， 1：速度异常， 2：里程异常， 3:时间异常
    */
    public function checkVisitorCheatRun($vid,$mileage, $elapsedtime, $updatetime, $detail_speed)
    {
        // 速度
    
        $averageSpeed = round(($mileage * 3600) / $elapsedtime, 2);

        if($averageSpeed > 20)
        {
            return 1;
        }

        $speedTimes = 0;  // 异常配速个数
        // if(!common::is_json($detail_speed))
        // {
        //     return 1;
        // }
        // foreach (json_decode($detail_speed) as $v)
        // {
        //     $v <= 2 && $speedTimes += 1;

        //         if($speedTimes >= 2)
        //         {
        //         return 1;
        //         }
        //     }
        // }
        // 里程
        $thisDayMileage = $this->visitorTotalMileageByDay($vid, date("Y-m-d", $updatetime));
        if($mileage > 105 || ($mileage + $thisDayMileage) > 105)
        {
            return 2;
        }

        // 时间
        $runDataSta = $updatetime - $elapsedtime;
        $runDataEnd = $updatetime;
        $prevEffectiveRun = $this->getVPrevEffectiveRun($vid,$runDataSta);
        $nextEffectiveRun = $this->getVNextEffectiveRun($vid,$runDataSta);
        
        if(!empty($prevEffectiveRun))
        {
            $preRunSta = $prevEffectiveRun['updatetime']-$prevEffectiveRun['elapsedtime'];
            $preRunEnd = $prevEffectiveRun['updatetime'];
           
            $flag = $this->timeSuperposition($runDataSta,$runDataEnd,$preRunSta,$preRunEnd);
            if($flag)
            {
                return 3;
            }
        }

        if(!empty($nextEffectiveRun))
        {
            $nextRunSta = $nextEffectiveRun['updatetime']-$nextEffectiveRun['elapsedtime'];
            $nextRunEnd = $nextEffectiveRun['updatetime'];
            $flag = $this->timeSuperposition($runDataSta,$runDataEnd,$nextRunSta,$nextRunEnd);
            if($flag)
            {
                return 3;
            }
        }
        return 0;
    }
     /**
     * 判断上传时间是否与有效时间重叠
     * @param $upTimeSta,$upTimeEnd
     * @param $testTimeSta,$testTimeEnd
     * @return boolen
     */
    public function timeSuperposition($upTimeSta,$upTimeEnd,$testTimeSta,$testTimeEnd)
    {
        if( $testTimeSta >= $upTimeEnd || $testTimeEnd <= $upTimeSta )
            return false;
        else
            return true;
    }
    /**
     * 用户某天跑步总里程
     * @param uid
     * @param date
     * @return   mileage
     */
    public function usertotalMileageByDay($uid, $date)
    {
        $dayStart = strtotime($date);
        $dayStart == FALSE && $dayStart = strtotime(date("Y-m-d"));
        $dayEnd = $dayStart + 86400;

        $mileage = $this->db->getone("select sum(mileage) from r_data where uid = '{$uid}' and updatetime >= '$dayStart' and updatetime < '{$dayEnd}' and is_delete = 0 and overSpeed = 0");

        return sprintf("%.2f", $mileage);
    }

    /**
     * 游客某天跑步总里程
     * @param uid
     * @param date
     * @return   mileage
     */
    public function visitorTotalMileageByDay($vid, $date)
    {
        $dayStart = strtotime($date);
        $dayStart == FALSE && $dayStart = strtotime(date("Y-m-d"));
        $dayEnd = $dayStart + 86400;

        $mileage = $this->db->getone("select sum(mileage) from r_visitor_data where vid = '{$vid}' and updatetime >= '$dayStart' and updatetime < '{$dayEnd}' and is_delete = 0 and overSpeed = 0");

        return sprintf("%.2f", $mileage);
    }
    /**
     * 用户最后一次跑步记录的数据
     * @param uid
     * @return   array()
     */
    public function userPreviousRun($uid)
    {
        $data = $this->db->getRow("select updatetime, elapsedtime from r_data where uid = '{$uid}' and is_delete = 0 and overSpeed = 0 limit 1");

        return $data;
    }
    /**
     * 当前用户跑步记录的前一条有效记录数据跑步数据
     * @param did
     * @return   array()
     */
    public function getPrevEffectiveRun($uid,$updatetime)
    {
//        $prevupdatetime = 0;
//        $data = $this->db->getRow("select updatetime, elapsedtime from r_data where did ='{$did}' and uid = '{$uid}' and is_delete = 0 and overSpeed = 0 limit 1");
       
        $prevupdatetime = $this->db->getRow("select updatetime,elapsedtime FROM r_data WHERE updatetime<='{$updatetime}' AND uid = '{$uid}'  AND is_delete = 0 AND overSpeed = 0 ORDER BY updatetime DESC LIMIT 1");
        return $prevupdatetime;
    }
     /**
     * 当前用户跑步记录的后一条有效记录数据跑步数据
     * @param did
     * @return   array()
     */
    public function getNextEffectiveRun($uid,$updatetime)
    {
      
        $nextupdatetime = $this->db->getRow("select updatetime,elapsedtime FROM r_data WHERE updatetime >='{$updatetime}' AND uid = '{$uid}'  AND is_delete = 0 AND overSpeed = 0 ORDER BY updatetime DESC LIMIT 1");
        return $nextupdatetime;
    }
    /**
     * 当前游客跑步记录的前一条有效记录数据跑步数据
     * @param did
     * @return   array()
     */
    public function getVPrevEffectiveRun($vid,$updatetime)
    {
//        $prevupdatetime = 0;
//        $data = $this->db->getRow("select updatetime, elapsedtime from r_data where did ='{$did}' and uid = '{$uid}' and is_delete = 0 and overSpeed = 0 limit 1");
       
        $prevupdatetime = $this->db->getRow("select updatetime,elapsedtime FROM r_visitor_data WHERE updatetime<='{$updatetime}' AND uid = '{$uid}'  AND is_delete = 0 AND overSpeed = 0 ORDER BY updatetime DESC LIMIT 1");
        return $prevupdatetime;
    }
     /**
     * 当前游客跑步记录的后一条有效记录数据跑步数据
     * @param did
     * @return   array()
     */
    public function getVNextEffectiveRun($vid,$updatetime)
    {
      
        $nextupdatetime = $this->db->getRow("select updatetime,elapsedtime FROM r_visitor_data WHERE updatetime >='{$updatetime}' AND uid = '{$uid}'  AND is_delete = 0 AND overSpeed = 0 ORDER BY updatetime DESC LIMIT 1");
        return $nextupdatetime;
    }
    /**
     * 获取用户变动的跑步记录
     * @param int $did
     * @param  array $modify 变动信息
     * @return  boolen
     */
    public function getUserModifyRun($uid, $type = 'add', $timeLine)
    {
        ini_set('memory_limit', '512M');

        $result = array();

        if(!$uid || !in_array($type, array('add', 'modify', 'delete')))
        {
            return $result;
        }
        $getDidsSql = "select did from r_data_modify where uid = '{$uid}' and modify_time > '{$timeLine}' and modify_type ";

        switch ($type)
        {
            case 'add':
                $getDidsSql .= '= 0';
                break;
            case 'modify':
                $getDidsSql .= '> 1';
                break;
            case 'delete':
                $getDidsSql .= '= 1';
                break;
        }

        $dids = $this->db->getCol($getDidsSql);
        if($dids)
        {
            $sql = '';
            $sqlIn = $this->base->load('push')->db_create_in($dids);
            switch ($type)
            {
                case 'add':
                    $sql = 'select d.*,de.coordinate,de.detail_speed_curve,de.detail_elevation,de.detail_elevation_curve,de.detail_footsteps,de.detail_footsteps_curve,de.detail_stride,de.detail_elevation_fold,de.detail_footsteps_fold from r_data d left join r_data_ext de on d.did=de.did where d.did '. $sqlIn;
                    break;
                case 'modify':
                    $sql = 'select did, order_id, overSpeed from r_data where did '. $sqlIn;
                    break;
                case 'delete':
                    $sql = 'select did, order_id from r_data where did '. $sqlIn;
                    break;
            }

            $add = $this->db->getAll($sql);
            
            foreach ($add as $key => $v) {
                $coordinate = @base64_decode($v['coordinate']);
                $uncompress = $coordinate ? @gzuncompress($coordinate) : FALSE;
                !$uncompress && $uncompress = @gzuncompress($v['coordinate']);

                if(!isset($v['coordinate']))
                {
                $v['coordinate'] = 0;
                $v['point_coordinate'] =0;
                $v['detail_speed'] = 0;
                $v['southWestPoint'] = 0;
                $v['northEastPoint'] = 0;
               
                }
                $v['coordinate'] = !$uncompress ? $v['coordinate'] : stripslashes($uncompress);
                $v['coordinate'] = trim($v['coordinate'], '"');
                $v['coordinate'] = $v['coordinate'] ? json_decode($v['coordinate'], true) : array();
                $data = $this->reCoordinate($v['coordinate']);
                $v['coordinate'] = $data;

                $v['point_coordinate'] = stripslashes($v['point_coordinate']);
                $v['point_coordinate'] = trim($v['point_coordinate'], '"');
                $v['point_coordinate'] = $v['point_coordinate'] ? json_decode($v['point_coordinate'], true) : array();
                $v['detail_speed'] = stripslashes($v['detail_speed']);
                $v['detail_speed'] = trim($v['detail_speed'], '"');
                $v['detail_speed'] = $v['detail_speed'] ? json_decode($v['detail_speed'], true) : array();

                $v['southWestPoint'] = stripslashes($v['southWestPoint']);
                $v['southWestPoint'] = trim($v['southWestPoint'], '"');
                $v['southWestPoint'] = $v['southWestPoint'] ? json_decode($v['southWestPoint'], true) : array();

                $v['northEastPoint'] = stripslashes($v['northEastPoint']);
                $v['northEastPoint'] = trim($v['northEastPoint'], '"');
                $v['northEastPoint'] = $v['northEastPoint'] ? json_decode($v['northEastPoint'], true ) : array();

                if($type == 'add')
                {
                    $v['detail_speed_curve'] = $v['detail_speed_curve'] ? json_decode($v['detail_speed_curve'], TRUE) : [];
                    $v['detail_elevation_curve'] = $v['detail_elevation_curve'] ? json_decode($v['detail_elevation_curve'], TRUE) : [];
                    $v['detail_elevation_fold'] = $v['detail_elevation_fold'] ? json_decode($v['detail_elevation_fold'], TRUE) : [];
                    $v['detail_footsteps_curve'] = $v['detail_footsteps_curve'] ? json_decode($v['detail_footsteps_curve'], TRUE) : [];
                    $v['detail_footsteps_fold'] = $v['detail_footsteps_fold'] ? json_decode($v['detail_footsteps_fold'], TRUE) : [];
                }

                if(!empty($v['medal'])){
                    $v['medal'] = stripslashes($v['medal']);
                    $v['medal'] = trim($v['medal'], '"');
                    $v['medal'] = json_decode($v['medal'], true );
                }else{
                    $v['medal'] = array();
                }

                if(!empty($v['record_img'])){
                    $v['record_img'] = stripslashes($v['record_img']);
                    $v['record_img'] = trim($v['record_img'], '"');
                    $v['record_img'] = json_decode($v['record_img'], true );
                }else{
                    $v['record_img'] = array();
                }

                $add[$key]['medal'] = $v['medal'];
                $add[$key]['record_img'] = $v['record_img'];
                $add[$key]['coordinate'] = $v['coordinate'];
                $add[$key]['detail_speed'] = $v['detail_speed'];
                $add[$key]['point_coordinate'] = $v['point_coordinate'];
                $add[$key]['southWestPoint'] = $v['southWestPoint'];
                $add[$key]['northEastPoint'] = $v['northEastPoint'];

                if($type == 'add')
                {
                    $add[$key]['detail_speed_curve'] = $v['detail_speed_curve'];
                    $add[$key]['detail_elevation'] = $v['detail_elevation'];
                    $add[$key]['detail_elevation_curve'] = $v['detail_elevation_curve'];
                    $add[$key]['detail_elevation_fold'] = $v['detail_elevation_fold'];
                    $add[$key]['detail_footsteps'] = $v['detail_footsteps'];
                    $add[$key]['detail_footsteps_curve'] = $v['detail_footsteps_curve'];
                    $add[$key]['detail_footsteps_fold'] = $v['detail_footsteps_fold'];
                    $add[$key]['detail_stride'] = $v['detail_stride'];
                }
            }
         
            $result = $add;

         
        }

        return $result;
    }
    /**
     * 用户跑步记录变动
     * @param int $did
     * @param  array $modify 变动信息
     * @return  boolen
     */
    public function runDataModify($did, $modify = array())
    {
        $result = false;

        if(!isset($modify['modify_type']) || !isset($modify['uid']))
        {
            return $result;
        }
        $modify['modify_type'] = intval($modify['modify_type']);
        if($modify['modify_type'] < 0 || $modify['modify_type'] > 3)
        {
            return $result;
        }

        $did = intval($did);
        $id = $this->db->getone("select id from r_data_modify where did = '{$did}'");

        $modify['did'] = $did;
        if($id)
        {
            unset($modify['add_time']);
            $result = $this->db->updateRowTable('r_data_modify', $modify) != false;
        }
        else
        {
            if(!isset($modify['add_time']))
            {
                $modify['add_time'] = time();
            }
            $result = $this->db->insertRowTable('r_data_modify', $modify) != false;
        }

        return $result;
    }
    /**
     * 数据异常转正常刷新
     * @param int $did
     * 
     * @return  boolen
     */

     public function addAbdateTnor($did)
     {
        $did = intval($did);

        $runData = $this->db->getRowTable('r_data', array(), "did = '{$did}' and is_delete = 0 and overSpeed != 0");
        if(empty($runData))
        {
            return false;
        }

        $query = $this->db->query("update r_data set overSpeed = 0  where did = '{$did}'");
        if($query == false)
        {
            return false;
        }

        $uid = $runData['uid'];

        $this->redis->hset(REDIS_PREFIX . 'runDataOrder_' . $uid, $runData['order_id'], 1);

        // 记录变更数据 $uid modify_type,runData(r_data)
        $modify = array(
                        'uid' => $uid,
                        'modify_type' => 2,
                        // 'add_time' => $this->base->time,
                        'modify_time' => $this->base->time
            );
        $rel = $this->runDataModify($did, $modify);

        // 更新用户累计数据
        $addData = array(
            'mileage' => round($runData['mileage'], 3),
            'elapsedtime' => intval($runData['elapsedtime']),
            'calorie' => $runData['calorie']
        );
        $this->cumRunData($uid, $addData);
        $upData = array();
        $userInfo = $this->base->load('client')->getUserInfo($uid);
        $upData['total_mileage'] = round($userInfo['total_mileage'] + $runData['mileage'], 3);
        $upData['level'] = common::getLevel($upData['total_mileage']);
        $upData['best_record'] = array();   //最佳成绩对应的did
        !empty($userInfo['best_record']) &&  $upData['best_record'] = json_decode($userInfo['best_record'], true);
        if($runData['mileage'] > $userInfo['max_mileage']){
            $upData['max_mileage'] = $runData['mileage'];
            $upData['best_record']['max_mileage'] = $did;
        }
        if($runData['elapsedtime'] > $userInfo['max_elapsedtime']){
            $upData['max_elapsedtime'] = $runData['elapsedtime'];
            $upData['best_record']['max_elapsedtime'] = $did;
        }
        !empty($runData['five_time']) && $runData['five_time'] < $userInfo['max_five_time'] && $upData['max_five_time'] = $runData['five_time'];
        if(!empty($runData['ten_time']) && $runData['ten_time'] < $userInfo['max_ten_time']){
            $upData['max_ten_time'] = $runData['ten_time'];
            $upData['best_record']['max_ten_time'] = $did;
        }
        if(!empty($runData['half_mtime']) && $runData['half_mtime'] < $userInfo['max_half_mtime']){
            $upData['max_half_mtime'] = $runData['half_mtime'];
            $upData['best_record']['max_half_mtime'] = $did;
        }
        if(!empty($runData['mara_time']) && $runData['mara_time'] < $userInfo['max_mara_time']){
            $upData['max_mara_time'] = $runData['mara_time'];
            $upData['best_record']['max_mara_time'] = $did;
        }
        if(!empty($runData['speed']) && $runData['speed'] > $userInfo['max_speed']){
            $upData['max_speed'] = $runData['speed'];
            $upData['best_record']['max_speed'] = $did;
        }
        $level = $userInfo['level'];
        $level < $upData['level'] && $this->runLevelUpRecord($uid, $upData['level'], $upData['total_mileage'],'', $runData['updatetime']);
        unset($upData['total_mileage']);
        !empty($upData['best_record']) && $upData['best_record'] = json_encode($upData['best_record']);
        $this->base->load('client')->setUserInfo($uid, $upData);

        if(isset($runData['target_rate']) && $runData['target_rate'] >= 1)
        {
            $this->base->load('client')->userEnergyChange($uid, 'target', $runData['mileage']);
        }
        elseif($runData['mileage'] >= 1)
        {
            $this->base->load('client')->userEnergyChange($uid, 'run', $runData['mileage']);
        }

        // 更新用户好友排行榜
        $this->updateUserFStandings($uid, $runData['mileage']);

        // 更新用户最近跑步记录
        $this->base->load('client')->getLatestRunRecord($uid, array(), true);
        
        $runRecord = array('mileage'        => $runData['mileage'],
                           'elapsedtime'    => $runData['elapsedtime'],
                           'city'           => $runData['city'],
                           'calorie'        => $runData['calorie'],
                           'updatetime'     => $runData['updatetime']
                           );

        // 更新用户跑步等级信息
        $this->base->load('client')->getUserLevelInfo($uid, TRUE);
        // 更新用户里程排名
        $this->setClientMileageStandingsRank($uid, round($userInfo['total_mileage'] + $runData['mileage'], 3));
        // 更新用户日跑步数据
        unset($runRecord['city']);
        $this->addDayRunData($uid, $runRecord);

        // 群组跑步数据
        $groupRunData = array('did' => $did,
          'mileage'        => $runData['mileage'],
          'elapsedtime'    => $runData['elapsedtime'],
          'city'           => $runData['city'],
          'calorie'        => $runData['calorie'],
          'updatetime'     => $runData['updatetime'],
          'five_time'     => $runData['five_time'],
          'ten_time'     => $runData['ten_time'],
          'half_mtime'     => $runData['half_mtime'],
          'mara_time'     => $runData['mara_time']
        );
        $rel = $this->base->load('group')->addGroupRunData($uid,$groupRunData);
        
        return true;
     }

      /**
     * 用户记录刷新
     * @param int $uid
     * 
     * @return  boolen
     */
     public function refreshUserRunRecord($uid)
     {
        $uid = intval($uid);

        if(empty($uid))
        {
            return false;
        }

        $upData = array();

        $userInfo = $this->db->getRowTable('r_user', array(), "uid={$uid}");

        $upData = $this->db->getRow("select sum(mileage) as total_mileage ,sum(elapsedtime) as total_elapsedtime,sum(calorie) as total_calorie,count(did) as total_rate,max(mileage) as max_mileage,max(elapsedtime) as max_elapsedtime from `r_data` where uid = '{$uid}' and is_delete =0 and overSpeed =0");
        if(empty($upData))
        {
            $upData = array('total_mileage' => 0.00,
                            'total_elapsedtime' => 0,
                            'total_calorie' => 0,
                            'total_rate'=> 0,
                            'max_mileage' =>0.00,
                            'max_elapsedtime' =>0
                ); 
        }
        $upData['uid'] = $uid;

        $upData['max_five_time'] = $this->db->getOne("select min(five_time) from `r_data` where uid = '{$uid}' and is_delete =0 and overSpeed =0 and five_time > 0");
        $upData['max_five_time'] = intval($upData['max_five_time']);

        $upData['max_ten_time'] = $this->db->getOne("select min(ten_time) from `r_data` where uid = '{$uid}' and is_delete =0 and overSpeed =0 and ten_time > 0");
        $upData['max_ten_time'] = intval($upData['max_ten_time']);

        $upData['max_half_mtime'] = $this->db->getOne("select min(half_mtime) from `r_data` where uid = '{$uid}' and is_delete =0 and overSpeed =0 and half_mtime > 0");
        $upData['max_half_mtime'] = intval($upData['max_half_mtime']);

        $upData['max_mara_time'] = $this->db->getOne("select min(mara_time) from `r_data` where uid = '{$uid}' and is_delete =0 and overSpeed =0 and mara_time > 0");
        $upData['max_mara_time'] = intval($upData['max_mara_time']);

        $rel = $this->db->updateRowTable('r_user',$upData);

        $this->redis->del(REDIS_PREFIX . 'UserInfo_' .$uid);

       return true;
     }

    /**
     * 通过UID和起始时间戳获取对应用户跑步里程
     * @param integer $uid
     * @param integer $startTime
     * @return integer
     */
    public function getUserMileageByUidAndStartTime($uid, $startTime)
    {
        $mileage = 0;

        $userInfo = $this->base->load('client')->getUserInfo($uid);

        if($userInfo)
        {
            $startTime && $startTime = intval($startTime);
            $mileage = $userInfo['total_mileage'];
            $startTime && $mileage = $this->db->getOne("select sum(mileage) from r_data where uid='{$uid}' and is_delete=0 and addtime>='{$startTime}' and overSpeed=0");
        }

        return $mileage;
    }

    /**
     * 获取用户某段时间内的最远记录
     * @param $uid
     * @param $stime
     * @param $etime
     * @return mixed
     */
    public function getMileageByTime($uid,$stime,$etime){
        return $this->db->getOne("select mileage from r_data where uid='{$uid}' and updatetime >= '$stime' and updatetime <= '$etime' order by mileage desc limit 1");
    }
    
    /**
     * 获取用户某段时间内的最快时速
     * @param $uid
     * @param $stime
     * @param $etime
     * @return mixed
     */
    public function getMaxSpeedByTime($uid,$stime,$etime){
        return $this->db->getOne("select speed from r_data where uid='{$uid}' and updatetime >= '$stime' and updatetime <= '$etime' order by speed desc limit 1");
    }
    
    /**
     * 获取用户某段时间内的总用时
     * @param $uid
     * @param $stime
     * @param $etime
     * @return mixed
     */
    public function getTotalElapsedtime($uid,$stime,$etime){
        return $this->db->getOne("select sum(elapsedtime) from r_data where uid='{$uid}' and updatetime >= '$stime' and updatetime <= '$etime' limit 1");
    }

    /**
     * 获取用户个人跑步目标
     * @param int $uid  用户ID
     * @param int $targetKey  目标时间范围（年周或年月）
     * @param int $targetType  目标类型（1：年周，2：年月）
     * @return integer
     */
    public function getUserSelfTarget($uid, $targetKey, $targetType = 'week')
    {
        $targetType = $targetType == 'week' ? 1 : 2;

        $userSelfTarget = $this->db->getOne("select mileage from r_user_self_target where uid='{$uid}' and `key`='{$targetKey}' and type='{$targetType}'");
        !$userSelfTarget && $userSelfTarget = 0;

        return $userSelfTarget;
    }

    /**
     * 设置用户个人跑步目标
     * @param int $uid  用户ID
     * @param int $targetKey  目标时间范围（年周或年月）
     * @param int $mileage  目标里程
     * @param int $targetType  目标类型（1：年周，2：年月）
     * @return boolean
     */
    public function setUserSelfTarget($uid, $targetKey, $mileage, $targetType = 'week')
    {
        $data = [
            'uid' => $uid,
            'key' => $targetKey,
            'mileage' => $mileage,
            'type' => $targetType == 'week' ? 1 : 2,
            'addtime' => time(),
        ];

        return $this->db->insertRow('r_user_self_target', $data, 1);
    }

    public function getRunDataByMonth($uid, $beginYmd, $endYmd)
    {
        return $this->db->getAll("select date_format(date,'%Y%m') ym,sum(mileage) mileage from r_data_day where uid='{$uid}' and date>='{$beginYmd}' and date<='{$endYmd}' and mileage > 0 group by ym order by ym desc");
    }

    public function getRunDataByDay($uid, $beginYmd, $endYmd)
    {
        return $this->db->getAll("select date ymd,sum(mileage) mileage from r_data_day where uid='{$uid}' and date>='{$beginYmd}' and date<='{$endYmd}' and mileage > 0 group by ymd order by ymd desc");
    }

    /**
     * 组装打点记录
     * @param $coordinate
     * @return array
     */
    public function reCoordinate($coordinate){
        $data = [];

        if($coordinate)
        {
            // 客户端2.8.0及以后版本都将跑步打点数据处理为二维数组，否则为一维数组
            $isAfter280 = $this->base->vn >= 2800;

            // 安卓2.8.0、2.8.1版本跑步打点数据需要将所有点聚合到二维数组的第一个中，否则客户端只能绘出二维数据第一个数组中的点
            $isAndroid280Fix = $this->base->projectId == 1 && $this->base->vn >= 2800 && $this->base->vn < 2820;

            if($isAfter280 && !$isAndroid280Fix){
                foreach($coordinate as $k=>$val){
                    if(!empty($val[0]))
                    {
                        $data[] = $val;
                    }
                    else
                    {
                        $data[0][] = $val;
                    }
                }

                foreach($data as $k => $val)
                {
                    $data[$k] = array_filter($val);
                }
            }else{
                foreach($coordinate as $k=>$val){
                    if(isset($val['lat'])){
                        $data[] = $val;
                    }else{
                        foreach($val as $item){
                            $data[] = $item;
                        }
                    }
                }
            }

            if($isAndroid280Fix)
            {
                $tmp = $data;
                $data = [];
                $data[] = $tmp;
            }
        }

        return $data;
    }
    
    /*
     * 更新用户累计数据
     */
    public function updateUserRecord($runData, $did){
        $uid = $runData['uid'];
        
        $addData = array(
            'mileage' => round($runData['mileage'], 3),
            'elapsedtime' => intval($runData['elapsedtime']),
            'calorie' => $runData['calorie']
        );
        $this->cumRunData($uid, $addData);
        $upData = array();
        $_upData = [];
        $userInfo = $this->base->load('client')->getUserInfo($uid);
        $upData['total_mileage'] = round($userInfo['total_mileage'] + $runData['mileage'], 3);
        $upData['level'] = common::getLevel($upData['total_mileage']);
        $upData['best_record'] = array();   //最佳成绩对应的did
        !empty($userInfo['best_record']) &&  $upData['best_record'] = json_decode($userInfo['best_record'], true);
        if($runData['mileage'] > $userInfo['max_mileage']){
            $upData['max_mileage'] = $runData['mileage'];
            $upData['best_record']['max_mileage'] = $did;
        }
        if($runData['elapsedtime'] > $userInfo['max_elapsedtime']){
            $upData['max_elapsedtime'] = $runData['elapsedtime'];
            $upData['best_record']['max_elapsedtime'] = $did;
        } 
        !empty($runData['five_time']) && (!$userInfo['max_five_time'] || $runData['five_time'] < $userInfo['max_five_time']) && $upData['max_five_time'] = $runData['five_time'];
        if(!empty($runData['ten_time']) && (!$userInfo['max_ten_time'] || $runData['ten_time'] < $userInfo['max_ten_time'])){
            $upData['max_ten_time'] = $runData['ten_time'];
            $upData['best_record']['max_ten_time'] = $did;
        }
        if(!empty($runData['half_mtime']) && (!$userInfo['max_half_mtime'] || $runData['half_mtime'] < $userInfo['max_half_mtime'])){
            $upData['max_half_mtime'] = $runData['half_mtime'];
            $upData['best_record']['max_half_mtime'] = $did;
        }
        if(!empty($runData['mara_time']) && (!$userInfo['max_mara_time'] || $runData['mara_time'] < $userInfo['max_mara_time'])){
            $upData['max_mara_time'] = $runData['mara_time'];
            $upData['best_record']['max_mara_time'] = $did;
        }
        if(!empty($runData['speed']) && $runData['speed'] > $userInfo['max_speed']){
            $upData['max_speed'] = $runData['speed'];
            $upData['best_record']['max_speed'] = $did;
        }
        //更新最长跑步天数
        $tmp_run_days = isset($userInfo['tmp_run_days']) ? $userInfo['tmp_run_days'] : 0;
        if(isset($runData['tmp_run_days']) && $runData['tmp_run_days'] != $tmp_run_days){
            $_upData['tmp_run_days'] = $runData['tmp_run_days'];
        }
        
        $level = $userInfo['level'];
        $level < $upData['level'] && $this->runLevelUpRecord($uid, $upData['level'], $upData['total_mileage'],'', $runData['updatetime']);
        unset($upData['total_mileage']);
        !empty($upData['best_record']) && $upData['best_record'] = json_encode($upData['best_record']);
        $this->base->load('client')->setUserInfo($uid, $upData);
        if(!empty($_upData)){
            $this->base->load('user')->setUserExt($uid, $_upData);
        }
    }
  
}
